home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Imaging Engine / ProcessShape.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  77.2 KB  |  2,877 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        ProcessShape.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.  
  6.      Version:    Technology:    Quickdraw GX 1.1.x
  7.       
  8.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. #include "GXToPSBuildConfig.h"
  12.  
  13. #include <GXGraphics.h>
  14. #include <GXExceptions.h>
  15. #include "GXGraphicsPriv.h"
  16.  
  17. #include "ShapeUtilities.h"
  18.  
  19. #include "OffscreenLibrary.h"
  20. #include "ProcessShape.h"
  21.  
  22. #ifdef GraphicsScript
  23.  
  24. #include <stdio.h>
  25. #include <FixMath.h>
  26.  
  27. #endif
  28.  
  29. /*-------------------------------------------------------------------------------
  30.     
  31.     TMTestMinMode
  32.     
  33.         this call tests for min mode which is useful for indexed bitmaps.
  34.  
  35. -------------------------------------------------------------------------------*/
  36. static Boolean TMTestMinMode( gxInk shink )
  37. {
  38.     gxTransferMode    shmode;
  39.     Boolean        result;
  40.     
  41.     short    count;
  42.         
  43.     result = true;        // assume that the transfer mode is min    
  44.  
  45.     GXGetInkTransfer( shink, &shmode );
  46.     
  47.     if( count = TMGetSpaceComponentCount( shmode.space ) )
  48.         {
  49.             gxTransferComponent        *trc = shmode.component;
  50.  
  51.             do
  52.                 {
  53.                     // there are two possible representations of or mode
  54.                     // one is gxCopy mode where ->sourceMinimum == ->sourceMaximum
  55.                     // and the other is
  56.                     // gxMinimum and ->sourceMinimum == 0 and ->sourceMaximum == 0xFFFF
  57.                 
  58.                     if( ( trc->mode == gxMinimumMode  &&
  59.                                 trc->sourceMinimum == 0        &&
  60.                                 trc->sourceMaximum == 0xFFFF )                        &&
  61.                             ( trc->deviceMinimum == 0x0000    &&
  62.                                 trc->clampMinimum == 0x0000        &&
  63.                                 trc->deviceMaximum == 0xFFFF    &&
  64.                                 trc->clampMaximum == 0xFFFF )  )
  65.                         {
  66.                             // do nothing; we have what we want
  67.                         }
  68.                     else
  69.                         {
  70.                             result = false;
  71.                             break;
  72.                         }
  73.                     
  74.                     trc += 1;
  75.  
  76.                 } while( 0 < --count );
  77.         }
  78.  
  79.     return( result );
  80.  
  81. }
  82. /*-------------------------------------------------------------------------------
  83.  
  84.     TMResolveColorSetOr
  85.         
  86.         this routine computes what the correct value is for a transfer mode that
  87.         simulates or mode.
  88.         
  89. -------------------------------------------------------------------------------*/
  90. static gxColor *TMResolveColorSetOr( gxColor *colorPtr, gxBitmap *bitsPtr, gxInk shInk )
  91. {
  92.     gxTransferMode        shmode;
  93.     gxInk                            tempInk = GXNewInk();
  94.     
  95.     colorPtr->space = bitsPtr->space;
  96.     colorPtr->profile = bitsPtr->profile;
  97.     
  98.     check( bitsPtr->space == gxIndexedSpace );
  99.     
  100.     colorPtr->element.indexed.set = bitsPtr->set;
  101.     
  102.     GXGetInkTransfer( shInk, &shmode );
  103.     GXSetInkTransfer( tempInk, &shmode );
  104.     
  105.     colorPtr->element.indexed.index = shmode.component[ 0 ].sourceMinimum;
  106.     
  107.     GXSetInkColor( tempInk, colorPtr );    
  108.     GXCombineColor( colorPtr, tempInk );
  109.     
  110.     GXConvertColor( colorPtr, gxRGBSpace, nil, nil );
  111.  
  112.     GXDisposeInk( tempInk );
  113.     return( colorPtr );
  114. }
  115. /*-------------------------------------------------------------------------------
  116.  
  117.     TMResolveOrModeBitmap
  118.         
  119.         this routine takes a shape which has a transfer mode which was derived
  120.         from quickdraw or mode and makes one that will render correctly even when
  121.         halftone to a raster device.
  122.         
  123. -------------------------------------------------------------------------------*/
  124. static gxShape TMResolveOrModeBitmap( gxShape sh )
  125. {
  126.     gxShape            sh2 = GXNewShape( gxFullType );
  127.     gxShapeType    cliptype;
  128.     
  129.     gxMapping    map;
  130.     gxBitmap    bits;
  131.     gxPoint        where;
  132.     
  133.     gxTransform        xform;
  134.     
  135.     gxColor                    shcolor;
  136.     gxColorProfile    profile;
  137.     
  138.     xform = GXGetShapeTransform( sh );
  139.     
  140.     check( GXGetShapeType( sh ) == gxBitmapType );
  141.     
  142.     GXGetBitmap( sh, &bits, &where );
  143.     
  144.     check( bits.pixelSize == 1 );
  145.     
  146.     if( profile = bits.profile )
  147.         {
  148.             GXCloneColorProfile( profile );
  149.             bits.profile = nil;
  150.             
  151.             // clips can't have profiles
  152.             
  153.             GXSetBitmap( sh, &bits, &where );
  154.         }
  155.     
  156.     cliptype = GetTransformClipType( xform );
  157.     
  158.     if( cliptype == gxRectangleType )
  159.         {
  160.             gxShape                clip;
  161.             gxRectangle        clipbox;
  162.             gxRectangle        testbox;
  163.             
  164.             // check to see if we can ignore the clip
  165.             
  166.             clip = GXGetTransformClip( xform );
  167.             GXGetRectangle( clip, &clipbox );
  168.             GXDisposeShape( clip );
  169.             
  170.             testbox.left = where.x;
  171.             testbox.top = where.y;
  172.             testbox.right = testbox.left + ff( bits.width );
  173.             testbox.bottom = testbox.top + ff( bits.height );
  174.             
  175.             if( GXContainsRectangle( &clipbox, &testbox ) )
  176.                 cliptype = gxFullType;
  177.         }
  178.      
  179.     if( cliptype == gxFullType )
  180.         {
  181.             GXGetShapeMapping( sh, &map );
  182.             GXSetShapeMapping( sh2, &map );
  183.         }
  184.     
  185.     GXSetShapeClip( sh2, sh );                // ## does this take into account the position ?
  186.  
  187.     check( GetTransformClipType( GXGetShapeTransform( sh2 ) ) == gxBitmapType );
  188.     
  189.     // here is the hard part -- we need to figure out what color to make this shape
  190.     
  191.     (void) TMResolveColorSetOr( &shcolor, &bits, GXGetShapeInk( sh ) );
  192.     
  193.     shcolor.profile = profile;
  194.     
  195.     GXSetShapeColor( sh2, &shcolor );
  196.     
  197.     if( profile ) GXDisposeColorProfile( profile );
  198.     
  199.     if( cliptype != gxFullType )
  200.         {
  201.             gxShape        p;
  202.             
  203.             p = GXNewPicture( 1, &sh2, nil, nil, nil );
  204.             GXDisposeShape( sh2 );
  205.  
  206.             check( GXGetShapeOwners( sh2 ) == 1 );
  207.  
  208.             GXSetShapeTransform( p, xform );
  209.             
  210.             sh2 = p;
  211.         }
  212.     
  213.     check( GXGetShapeOwners( sh2 ) == 1 );
  214.             
  215.     return( sh2 );
  216. }
  217. /*-------------------------------------------------------------------------------
  218.     
  219.     TMAdjustOffscreenDevice
  220.     
  221.         this routine adjusts the offscreen device so that patterns draw 
  222.         correctly.
  223.  
  224. -------------------------------------------------------------------------------*/
  225. static void TMAdjustOffscreenDevice( offscreen *os, gxPoint *wherePtr )
  226. {
  227.     gxMapping        map;
  228.     
  229.     GXGetViewDeviceMapping( os->device, &map );
  230.     MoveMapping( &map, -wherePtr->x, -wherePtr->y );
  231.     GXSetViewDeviceMapping( os->device, &map );
  232. }
  233.  
  234. /*-------------------------------------------------------------------------------
  235.     
  236.     TMGetShapeBounds
  237.     
  238.         this routine gets the global bounding box for a shape
  239.  
  240. -------------------------------------------------------------------------------*/
  241. void TMGetShapeBounds( gxRectangle  *shbboxPtr, gxShape sh, TShapeStack *stackPtr,
  242.     TBBoxParam *bpptr )
  243. {    
  244.     gxRectangle emptybox = { 0, 0, 0, 0 };
  245.     gxRectangle fullbox = { 0x80000000, 0x80000000, 0x7FFFFFFF, 0x7FFFFFFF };
  246.     
  247.     gxRectangle shbbox;
  248.     
  249.     gxShapeType shType;
  250.     
  251.     // next we look at the fill 
  252.     
  253.     shType = GXGetShapeType( sh );
  254.     
  255.     // there are certain shapes that get treated especially
  256.  
  257.     if( shType == gxPictureType )
  258.         {
  259.             TShapeStack        stack;
  260.             OSErr                 status;
  261.             
  262.             shbbox = emptybox;        // we start with an empty rectangle and then add the bbox's
  263.                                                         // for each of the shapes in the picture
  264.             nrequire( status = TMNewStack( &stack ), MakeStackFailed );
  265.             
  266.             status = TMPushShape( &stack, sh );        // the picture shape
  267.             
  268.             for(;;)
  269.                 {
  270.                     gxShape    sh2;
  271.                                         
  272.                     gxRectangle sh2bbox;
  273.                     
  274.                     sh2 = TMNextShape( &stack );
  275.                     
  276.                     if( sh2 )
  277.                         {
  278.                             TMGetShapeBounds( &sh2bbox, sh2, &stack, bpptr );
  279.                                             
  280.                             if( emptyrectangle( &shbbox ) )
  281.                                 shbbox = sh2bbox;
  282.                             else
  283.                                 GXUnionRectangle( &shbbox, &shbbox, &sh2bbox );
  284.                                                                 
  285.                             TMFreeShape( &stack );
  286.                         }
  287.                     else
  288.                         break;
  289.                 }
  290.         
  291.             // dispose of the stack
  292.             
  293.             TMDisposeStack( &stack );
  294.         }
  295.     else if( shType == gxFullType )
  296.         {
  297.             shbbox = bpptr->pagebounds;
  298.         }
  299.     else
  300.         {
  301.             gxMapping        themap;
  302.             gxShapeFill    shFill;
  303.             
  304.             switch( shFill = GXGetShapeFill( sh ) )
  305.                 {
  306.                     case gxNoFill:
  307.                         shbbox = emptybox; goto skipMappingComputation;
  308.                         break;
  309.                         
  310.                     case gxOpenFrameFill:
  311.                     case gxClosedFrameFill:
  312.                     case gxEvenOddFill:
  313.                     case gxWindingFill:
  314.                         GXGetShapeLocalBounds( sh, &shbbox );
  315.                         
  316.                         // for text shapes, we give the bounds a bit of slop due to non-linear scaling
  317.                         if( (shFill < gxEvenOddFill && GXGetShapePen( sh ) == 0) || shType == gxTextType || shType == gxGlyphType || shType == gxLayoutType ) 
  318.                             {
  319.                                 shbbox.left     -= bpptr->pixelsize.x;
  320.                                 shbbox.top         -= bpptr->pixelsize.y;
  321.                                 shbbox.right     += bpptr->pixelsize.x;
  322.                                 shbbox.bottom += bpptr->pixelsize.y;
  323.                             }
  324.                         break;
  325.                     
  326.                     case gxInverseFill:
  327.                         shbbox = bpptr->pagebounds;
  328.                         break;
  329.                 }            
  330.             if( ! emptyrectangle( &shbbox ) )
  331.                 {
  332.                     gxTransform        *trptr;
  333.                     long        indx;
  334.                     
  335.                     gxPoint        corners[ 4 ];
  336.                                         
  337.                     // the next loop concatates the clips and mapping for the shapes going up
  338.                     // the picture hierachy.  note that because the first clip and mapping come
  339.                     // from the shape we do those first and then work backwards through the stack
  340.                     
  341.                     if( stackPtr != nil )
  342.                         {
  343.                             check( stackPtr->tr.top <= stackPtr->tr.mark );
  344.                             
  345.                             if( 0 <= ( indx = ( stackPtr->tr.mark - stackPtr->tr.top ) - 1 ) )
  346.                                 {
  347.                                     HLock((Handle) stackPtr->tr.list );
  348.                             
  349.                                     trptr = & (* stackPtr->tr.list)[ stackPtr->tr.mark - 1 ];
  350.                                 }
  351.                         }
  352.                     else
  353.                         {
  354.                             indx = -1;
  355.                         }
  356.                                         
  357.                     for(;;)
  358.                         {                                                        
  359.                             // now we look in the shape stack and get the next transform and the
  360.                             // next clip that will be applied the next time through
  361.                                                                 
  362.                             if( ( 0 <= indx ) && ( ! emptyrectangle( &shbbox ) ) )
  363.                                 {                                            
  364.                                     (void) GXGetTransformMapping( *trptr, &themap );
  365.                                     
  366.                                     trptr -= 1;        // advance (backwards) the mark and counter
  367.                                     indx -= 1;
  368.                                 }
  369.                             else break;        // we are done
  370.  
  371.                             // we take the rectangle after it has been clipped and mapped it through the
  372.                             // transform. note that because the transform can apply rotation and 
  373.                             // perspective we actually need to map each of the four corners of the 
  374.                             // rectangle and not just the opposite corners of the rectangle
  375.  
  376.                             TMBoundsToPoints( corners, &shbbox );
  377.                             MapPoints( &themap, 4, corners );
  378.                             TMPointsToBounds( &shbbox, corners );
  379.                         }
  380.                     
  381.                     if( stackPtr != nil ) HUnlock((Handle) stackPtr->tr.list );
  382.                 }
  383.         }
  384.  
  385.     // before we set the rectangle we need to make sure that the rectangle that we have
  386.     // does not overflow the pagebounds that we were given
  387.  
  388. skipMappingComputation:    
  389.  
  390.     if( ! emptyrectangle( &shbbox ) )
  391.         GXIntersectRectangle( &shbbox, &shbbox, &( bpptr->pagebounds ) );        // force the bounds
  392.  
  393. MakeStackFailed:
  394.  
  395.     *shbboxPtr = shbbox;
  396. }
  397.  
  398. /*-------------------------------------------------------------------------------
  399.     
  400.     TMNewStack
  401.     
  402.         this routine creates a stack for picture references
  403.  
  404. -------------------------------------------------------------------------------*/
  405.  
  406. OSErr TMNewStack( TShapeStack *stackPtr )
  407. {
  408.     OSErr status;
  409.         
  410.     stackPtr->mark         = 0;
  411.     stackPtr->tr.top     = 0;
  412.     stackPtr->tr.mark  = 0;
  413.     stackPtr->tr.seed  = 0;
  414.     stackPtr->index         = 0;
  415.     
  416.     stackPtr->newstyle            = stackPtr->savestyle         =        nil;
  417.     stackPtr->newink                 = stackPtr->saveink                =        nil;
  418.     stackPtr->newtransform    = stackPtr->savetransform =     nil;
  419.  
  420.     stackPtr->stack = ( TShapeNMark **) NewHandle( kStackListIncrement * sizeof( TShapeNMark ) );    
  421.     nrequire( status = MemError(), ShapeStackFailed );
  422.     
  423.     stackPtr->tr.list = ( gxTransform ** ) NewHandle( kStackListIncrement * sizeof( gxTransform ) );
  424.     nrequire( status = MemError(), TransformStackFailed );
  425.  
  426.     stackPtr->count      = kStackListIncrement;
  427.     stackPtr->tr.count = kStackListIncrement;
  428.     
  429.     GXIgnoreGraphicsNotice( shape_already_in_primitive_form );
  430.  
  431.     return( noErr );
  432.  
  433.     DisposeHandle((Handle) stackPtr->tr.list );
  434.  
  435. TransformStackFailed:
  436.     DisposeHandle((Handle) stackPtr->stack );
  437.  
  438. ShapeStackFailed:    
  439.     return( status );
  440. }
  441. /*-------------------------------------------------------------------------------
  442.     
  443.     TMDisposeStack
  444.     
  445.         this routine disposes of a stack of pictures and references.
  446.  
  447. -------------------------------------------------------------------------------*/
  448.  
  449. void TMDisposeStack( TShapeStack *stackPtr )
  450. {
  451.     check( stackPtr->mark == 0 );
  452.     check( stackPtr->tr.top == 0 );
  453.     
  454.     DisposeHandle((Handle) stackPtr->stack );
  455.     stackPtr->mark     = 0;
  456.     stackPtr->count = 0;
  457.             
  458.     if( 0 < stackPtr->tr.mark )
  459.         {
  460.             short                indx;
  461.             gxTransform     *trptr;
  462.             
  463.  
  464.             indx = stackPtr->tr.mark - 1;
  465.  
  466.             HLock((Handle) stackPtr->tr.list );
  467.  
  468.             trptr = & (* stackPtr->tr.list)[ 0 ];
  469.  
  470.             for( ; indx >= 0; --indx )
  471.                 {
  472.                     GXDisposeTransform( *trptr++ );
  473.                 }
  474.             
  475.             HUnlock((Handle) stackPtr->tr.list );
  476.         }
  477.  
  478.     DisposeHandle((Handle) stackPtr->tr.list );
  479.     
  480.     stackPtr->tr.mark     = 0;
  481.     stackPtr->tr.count     = 0;
  482.     
  483.     GXPopGraphicsNotice( );            // pop the notices from TMNewStack
  484. }
  485.  
  486. /*-------------------------------------------------------------------------------
  487.     
  488.     TMPushShape
  489.     
  490.         this routine adds a shape and picture to the stack
  491.  
  492. -------------------------------------------------------------------------------*/
  493.  
  494. OSErr TMPushShape( TShapeStack *stackPtr, gxShape sh )
  495. {
  496.     OSErr status = noErr;
  497.  
  498.     TShapeNMark    *smptr;
  499.     long                  count;
  500.         
  501.     // check to see if we have enough room to push the shape
  502.     
  503.     if( stackPtr->count <= stackPtr->mark )
  504.         {
  505.             // we need to grow the stack
  506.             
  507.             SetHandleSize((Handle) stackPtr->stack, sizeof( TShapeNMark ) * 
  508.                                                                                          ( stackPtr->count + kStackListIncrement ) );
  509.             nrequire( status = MemError(), GrowStackFailed );
  510.             
  511.             stackPtr->count += kStackListIncrement;
  512.         }
  513.     
  514.     // we have place to put the information now
  515.     
  516.     if( GXGetShapeType( sh ) == gxPictureType )
  517.         count = GXGetPicture( sh, nil, nil, nil, nil );
  518.     else
  519.         count = 1;
  520.  
  521.     HLock((Handle) stackPtr->stack); smptr = &( (* stackPtr->stack)[ stackPtr->mark ] );
  522.     
  523.     smptr->sh      = sh;
  524.     smptr->mark  = 0;
  525.     smptr->count = count;
  526.     
  527.     // the picture shapes do not get 'freed' and therefore the owner
  528.     // count of style, ink, and transform are already set for this -- no need to clone them
  529.     
  530.     smptr->savestyle = stackPtr->savestyle;
  531.     smptr->saveink = stackPtr->saveink;
  532.     smptr->savetransform = stackPtr->savetransform;
  533.     
  534.     HUnlock((Handle) stackPtr->stack );
  535.  
  536.     stackPtr->savestyle = nil;                // make sure we clean these for the next shape to use
  537.     stackPtr->saveink = nil;                    // -- these objects get disposed at TMPopShape
  538.     stackPtr->savetransform = nil;
  539.         
  540.     stackPtr->mark += 1;        // bump the stack mark
  541.     
  542.     // we need to append the transform of this picture shape to the transform list in the stack
  543.     // because of the way the stack manipulation scheme works the transform that we get from 
  544.     // the shape is always the correct one -- that is, the shapes on the stack always represent
  545.     // the 'correct' the state
  546.     
  547.     status = TMConcatenateTransform( &( stackPtr->tr ), GXGetShapeTransform( sh ) );
  548.     
  549.     // we are done
  550.     
  551. GrowStackFailed:
  552.  
  553.     return( status );
  554. }
  555.  
  556. /*-------------------------------------------------------------------------------
  557.     
  558.     TMPopShape
  559.     
  560.         this routine removes the reference to the topmost entry in the stack
  561.  
  562. -------------------------------------------------------------------------------*/
  563. void TMPopShape( TShapeStack *stackPtr )
  564. {
  565.     TShapeNMark    *smptr;
  566.     
  567.     short    indx;
  568.     
  569.     gxTransform        *trptr;
  570.  
  571.     check( 0 < stackPtr->mark );
  572.     
  573.     HLock((Handle) stackPtr->stack );        // lock this down so that we can call gx graphics
  574.     
  575.     smptr = &( (*stackPtr->stack)[ stackPtr->mark - 1 ] );
  576.  
  577.     if( smptr->savestyle )
  578.         {
  579.             GXSetShapeStyle( smptr->sh, smptr->savestyle );
  580.             GXDisposeStyle( smptr->savestyle );
  581.         }
  582.  
  583.     if( smptr->saveink )
  584.         {
  585.             GXSetShapeInk( smptr->sh, smptr->saveink );
  586.             GXDisposeInk( smptr->saveink );
  587.         }
  588.     
  589.     if( smptr->savetransform )
  590.         {
  591.             GXSetShapeTransform( smptr->sh, smptr->savetransform );
  592.             GXDisposeTransform( smptr->savetransform );
  593.         }
  594.     
  595.     HUnlock((Handle) stackPtr->stack );
  596.     
  597.     stackPtr->mark -= 1;
  598.     
  599.     if( ( kStackListIncrement * 2 ) <  ( stackPtr->count - stackPtr->mark ) )
  600.         {
  601.             // the stack is too big and we need to shirk it
  602.             
  603.             SetHandleSize((Handle) stackPtr->stack, sizeof( TShapeNMark ) * 
  604.                                                                                      ( stackPtr->count - kStackListIncrement ) );
  605.                                                                                      
  606.             ncheck( MemError() );        // shrinking a handle should never result in an error
  607.             
  608.             stackPtr->count -= kStackListIncrement;
  609.         }
  610.  
  611.     // because there is no good way to un-concatenate a transform we need to
  612.     // rebuild the list to all the shapes - 1
  613.         
  614.     if( 0 < stackPtr->mark )
  615.         {
  616.             smptr = &( (*stackPtr->stack)[ stackPtr->mark - 1 ] );        // a pointer to the last shape
  617.             
  618.             // we only do this if the next shape is not the last in the picture
  619.             
  620.             if( smptr->mark < smptr->count )
  621.                 {
  622.                     if( 0 <= ( indx = ( stackPtr->tr.mark - stackPtr->tr.top ) - 1 ) )    // transforms on the stack
  623.                         {
  624.                             HLock((Handle) stackPtr->tr.list );
  625.                             
  626.                             trptr = & (* stackPtr->tr.list)[ stackPtr->tr.top ];
  627.                             
  628.                             for( ; indx >= 0; --indx )
  629.                                 {
  630.                                     GXDisposeTransform( *trptr++ );
  631.                                 }
  632.                             
  633.                             HUnlock((Handle) stackPtr->tr.list );
  634.                         }
  635.                     
  636.                     // because this is the only place where we remove items of the transform stack
  637.                     // we check to see if it is suitable to be shrunk
  638.                 
  639.                     if( ( kStackListIncrement * 2 ) < ( stackPtr->tr.count - stackPtr->tr.mark ) )
  640.                         {
  641.                             SetHandleSize((Handle) stackPtr->tr.list, sizeof( gxTransform ) *
  642.                                                                                                     ( stackPtr->tr.count - kStackListIncrement ) );
  643.                             ncheck( MemError() ); // ditto
  644.                             
  645.                             stackPtr->tr.count -= kStackListIncrement;
  646.                         }
  647.                 
  648.                     // at this point there are not transforms on the stack and tr.mark = tr.top
  649.                     
  650.                     stackPtr->tr.mark = stackPtr->tr.top;        // we now restore the stack to the top
  651.                     stackPtr->tr.seed += 1;                                    // make sure to invalidate the seed
  652.                     
  653.                     // now we push the transform of each of the shapes that remain on the regular stack
  654.                     
  655.                     indx = stackPtr->mark - 1;            // the count of the shapes on the stack (0 based)
  656.                     
  657.                     if( 0 <= indx )
  658.                         {
  659.                             HLock((Handle) stackPtr->stack );
  660.                             
  661.                             smptr = & (* stackPtr->stack)[ 0 ];
  662.                             
  663.                             for( ; indx >= 0; --indx )
  664.                                 {
  665.                                     (void) TMConcatenateTransform( &( stackPtr->tr ), GXGetShapeTransform( smptr->sh ) );
  666.                                     
  667.                                     smptr += 1;    // advance the pointer
  668.                                 }
  669.                             
  670.                             HUnlock((Handle) stackPtr->stack );
  671.                         }
  672.                 }                        
  673.         }
  674. }
  675. /*-------------------------------------------------------------------------------
  676.     
  677.     TMRewindStack
  678.     
  679.         this routine resets the field in the stack so that it can be used again
  680.         from the beginning.  note that this routine does not clear the transforms 
  681.         that are located above the top of the transform stack
  682.  
  683. -------------------------------------------------------------------------------*/
  684. void TMRewindStack( TShapeStack *stackPtr )
  685. {
  686.     TShapeNMark    *smptr;
  687.     
  688.     short    count;
  689.     
  690.     check( 0 < stackPtr->mark );        // make sure that we have something to rewind in
  691.         
  692.     if( 1 < ( count = stackPtr->mark ) ) // this is how many shapes there are on the stack
  693.         {
  694.             short    indx = count - 1;
  695.             
  696.             HLock((Handle) stackPtr->stack ); smptr = & (* stackPtr->stack)[ indx ];
  697.             
  698.             for( ; 1 <= indx ; --indx )
  699.                 {
  700.  
  701. #if DEBUGLEVEL>0
  702.  
  703.                     if( smptr->sh == nil ) Debugger( );
  704.  
  705.                     GXValidateShape( smptr->sh );
  706.                     
  707.                     if( smptr->savestyle ) GXValidateStyle( smptr->savestyle );
  708.                     if( smptr->saveink ) GXValidateInk( smptr->saveink );
  709.                     if( smptr->savetransform ) GXValidateTransform( smptr->savetransform );
  710. #endif
  711.                 
  712.                     if( smptr->savestyle )
  713.                         {
  714.                             GXSetShapeStyle( smptr->sh, smptr->savestyle );
  715.                             GXDisposeStyle( smptr->savestyle );
  716.                         }
  717.                     
  718.                     if( smptr->saveink )
  719.                         {
  720.                             GXSetShapeInk( smptr->sh, smptr->saveink );
  721.                             GXDisposeInk( smptr->saveink );
  722.                         }
  723.                         
  724.                     if( smptr->savetransform )
  725.                         {
  726.                             GXSetShapeTransform( smptr->sh, smptr->savetransform );
  727.                             GXDisposeTransform( smptr->savetransform );
  728.                         }
  729.  
  730.                     smptr -= 1;
  731.                 }
  732.             
  733.             // now we reset the mark on the topmost shape and the index in the stack
  734.                         
  735.             HUnlock((Handle) stackPtr->stack );
  736.             
  737.             stackPtr->mark = 1;        // leave the top shape on the stack            
  738.         }
  739.         
  740.     // now we deal with all of the transforms
  741.     
  742.     
  743.     if( count = stackPtr->tr.mark - stackPtr->tr.top )
  744.         {
  745.             gxTransform        *trptr;
  746.             
  747.             short    indx = count - 1;
  748.             
  749.             HLock((Handle) stackPtr->tr.list );
  750.  
  751.             trptr = & (* stackPtr->tr.list)[ stackPtr->tr.top ];
  752.             
  753.             for( ; indx >= 0 ; --indx )
  754.                 {
  755.                     GXDisposeTransform( *trptr++ );                    
  756.                 }
  757.                 
  758.             HUnlock((Handle) stackPtr->tr.list );
  759.             
  760.             stackPtr->tr.mark = stackPtr->tr.top;
  761.         }
  762.         
  763.     // make sure that the mark on the stack points to the right shape
  764.     
  765.     smptr = & (* stackPtr->stack)[ 0 ];
  766.     smptr->mark = 0;
  767.     
  768.     // and finally we restore the index for the shape and push the transform for it
  769.     
  770.     stackPtr->index = 0;
  771.  
  772.     (void) TMConcatenateTransform( &( stackPtr->tr ), GXGetShapeTransform( smptr->sh ) );
  773. }
  774.  
  775. /*-------------------------------------------------------------------------------
  776.     
  777.     TMPeekShape
  778.     
  779.         this routine adds a shape and picture to the stack
  780.  
  781. -------------------------------------------------------------------------------*/
  782. void TMPeekShape( gxShape *shptr, long *markptr, long *countptr, TShapeStack *stackPtr )
  783. {
  784.     TShapeNMark    *smptr;
  785.  
  786.     check( 0 < stackPtr->mark );
  787.  
  788.     smptr = &( (* stackPtr->stack)[ stackPtr->mark - 1 ] );
  789.     
  790.     if( shptr != nil ) *shptr = smptr->sh;
  791.     if( markptr != nil ) *markptr = smptr->mark;
  792.     if( countptr != nil ) *countptr = smptr->count;
  793. }
  794.  
  795. /*-------------------------------------------------------------------------------
  796.     
  797.     TMGrabShape
  798.     
  799.         this shape returns the shape to which the stack points to currently
  800.         setting the style and ink appropriately.  the clients should call 
  801.         TMFreeShape after it is done processing the shape
  802.  
  803. -------------------------------------------------------------------------------*/
  804. gxShape TMGrabShape( TShapeStack *stackPtr )
  805. {
  806.     TShapeNMark    *smptr;
  807.  
  808.     gxShape        sh;
  809.     
  810.     check( 0 < stackPtr->mark  );
  811.  
  812.     smptr = &( (*stackPtr->stack)[ stackPtr->mark - 1 ] );
  813.     
  814.     smptr->mark += 1;
  815.  
  816. #ifndef print_backwards
  817.     (void) GXGetPictureParts( smptr->sh, smptr->mark, 1, &stackPtr->sh, 
  818.                                                 &stackPtr->newstyle, &stackPtr->newink, &stackPtr->newtransform );
  819. #else
  820.     (void) GXGetPictureParts( smptr->sh, smptr->count - smptr->mark + 1, 1, &stackPtr->sh, 
  821.                                                 &stackPtr->newstyle, &stackPtr->newink, &stackPtr->newtransform );
  822. #endif
  823.     sh = stackPtr->sh;
  824.  
  825. #if DEBUGLEVEL>0
  826.     GXValidateShape( sh );
  827.     
  828.     if( stackPtr->newstyle ) GXValidateStyle( stackPtr->newstyle );
  829.     if( stackPtr->newink ) GXValidateInk( stackPtr->newink );
  830.     if( stackPtr->newtransform ) GXValidateTransform( stackPtr->newtransform );
  831. #endif
  832.  
  833.     GXIgnoreGraphicsNotice( style_already_set );
  834.     GXIgnoreGraphicsNotice( ink_already_set );
  835.     GXIgnoreGraphicsNotice( transform_already_set );
  836.     
  837.     // note: we need to clone the shapes attributes before we fold them into the shape because
  838.     // everytime that SetShapeXXXX() is called it disposes of the shapes current attribute
  839.     // and it sets it to be the new one.
  840.         
  841.     if( stackPtr->newstyle )
  842.         {
  843.             stackPtr->savestyle = GXCloneStyle( GXGetShapeStyle( sh ) );
  844.             GXSetShapeStyle( sh, stackPtr->newstyle );            
  845.         }
  846.     
  847.     if( stackPtr->newink )
  848.         {
  849.             stackPtr->saveink = GXCloneInk( GXGetShapeInk( sh ) );
  850.             GXSetShapeInk( sh, stackPtr->newink );
  851.         }
  852.  
  853.     if( stackPtr->newtransform )
  854.         {
  855.             stackPtr->savetransform = GXCloneTransform( GXGetShapeTransform( sh ) );
  856.             GXSetShapeTransform( sh, stackPtr->newtransform );
  857.         }
  858.     else
  859.         {
  860.             gxTransform        xform;
  861.             
  862.             if( 1 >= GXGetTransformOwners( xform = GXGetShapeTransform( sh ) ) 
  863.                     && GXGetShapeType( sh ) == gxPictureType )
  864.                 {
  865.                     check( GXGetTransformOwners( xform ) == 1 );
  866.  
  867.                     stackPtr->savetransform = GXCloneTransform( xform );
  868.                     
  869.                     xform = GXCopyToTransform( nil, xform );
  870.                     GXSetShapeTransform( sh, xform );
  871.                     GXDisposeTransform( xform );
  872.                 }
  873.         }
  874.  
  875.     GXPopGraphicsNotice();
  876.     GXPopGraphicsNotice();    
  877.     GXPopGraphicsNotice();
  878.     
  879.     // this tells us what place we're at
  880.     
  881.     if( GXGetShapeType( sh ) != gxPictureType ) stackPtr->index += 1;
  882.     
  883.     return( sh );
  884. }
  885.  
  886. /*-------------------------------------------------------------------------------
  887.     
  888.     TMNextShape
  889.     
  890.         this routine returns the next available shape which is not a picture
  891.  
  892. -------------------------------------------------------------------------------*/
  893. gxShape TMNextShape( TShapeStack *stackPtr )
  894. {
  895.     OSErr status;
  896.     
  897.     gxShape sh = nil;
  898.  
  899.     for(;;)
  900.         {
  901.             long        indx;
  902.             long        count;
  903.             
  904.             TMPeekShape( nil, &indx, &count, stackPtr );
  905.             
  906.             if( indx < count )
  907.                 {        
  908.                     sh = TMGrabShape( stackPtr );
  909.                     
  910.                     if( GXGetShapeType( sh ) == gxPictureType )
  911.                         {
  912.                             nrequire( status = TMPushShape( stackPtr, sh ), PushShapeFailed );
  913.                         }
  914.                     else
  915.                         break;
  916.                 }
  917.             else
  918.                 {
  919.                     TMPopShape( stackPtr );
  920.                 }
  921.                 
  922.             if( emptystackq( stackPtr ) ) { sh = nil; break; }
  923.         } 
  924.  
  925.     return( sh );
  926.  
  927. PushShapeFailed:
  928.     return( nil );
  929. }
  930. /*-------------------------------------------------------------------------------
  931.     
  932.     TMSkipShape
  933.     
  934.         this routine advances the shape marker
  935.  
  936. -------------------------------------------------------------------------------*/
  937. void TMSkipShape( TShapeStack *stackPtr )
  938. {
  939.     if( TMNextShape( stackPtr ) )
  940.         {    
  941.             TMFreeShape( stackPtr );
  942.         }
  943. }
  944.  
  945. /*-------------------------------------------------------------------------------
  946.     
  947.     TMFreeShape
  948.     
  949.         this routine undoes all the changes that TMGrabShape has to do in order 
  950.         to work
  951.  
  952. -------------------------------------------------------------------------------*/
  953. void TMFreeShape( TShapeStack *stackPtr )
  954. {
  955.     gxShape sh = stackPtr->sh;
  956.  
  957.     GXIgnoreGraphicsNotice( style_already_set );
  958.     GXIgnoreGraphicsNotice( ink_already_set );
  959.     GXIgnoreGraphicsNotice( transform_already_set );    
  960.  
  961.     if( stackPtr->savestyle != nil )
  962.         {
  963.             GXSetShapeStyle( sh, stackPtr->savestyle );
  964.             GXDisposeStyle( stackPtr->savestyle );
  965.             stackPtr->savestyle = nil;
  966.         }
  967.         
  968.     if( stackPtr->saveink != nil )
  969.         {
  970.             GXSetShapeInk( sh, stackPtr->saveink );
  971.             GXDisposeInk( stackPtr->saveink );
  972.             stackPtr->saveink = nil;
  973.         }
  974.  
  975. #ifdef print_transform_mapping
  976.     {
  977.         gxTransform        xform;
  978.         long map[ 9 ];
  979.         
  980.         GXGetTransformMapping( xform = GXGetShapeTransform( sh ) , (gxMapping *) & map[ 0 ] );
  981.         dprintf( notrace, "after: 0x%8X\n[ %F %F %T ]\n[ %F %F %T ]\n[ %F %F %T ]",
  982.                                 xform,
  983.                                 map[ 0 ], map[ 1 ], map[ 2 ],
  984.                                 map[ 3 ], map[ 4 ], map[ 5 ],
  985.                                 map[ 6 ], map[ 7 ], map[ 8 ] );
  986.     }
  987. #endif
  988.  
  989.     if( stackPtr->savetransform != nil )
  990.         {
  991.             GXSetShapeTransform( sh, stackPtr->savetransform );
  992.             GXDisposeTransform( stackPtr->savetransform );
  993.             stackPtr->savetransform = nil;
  994.         }
  995.  
  996.     GXPopGraphicsNotice();
  997.     GXPopGraphicsNotice();    
  998.     GXPopGraphicsNotice();
  999.  
  1000. }
  1001. /*-------------------------------------------------------------------------------
  1002.     
  1003.     TMFixOverrides
  1004.     
  1005.         this routine sets the overrides on a shape and saves the shapes normal 
  1006.         attributes in a special data structure
  1007.  
  1008. -------------------------------------------------------------------------------*/
  1009. void TMFixOverrides( gxShape sh, gxStyle newstyle, gxInk newink, gxTransform newtransform,
  1010.                                          TTMShapeOverrides *overPtr )
  1011. {
  1012.     overPtr->sh = sh;
  1013.     
  1014.     GXIgnoreGraphicsNotice( style_already_set );
  1015.     GXIgnoreGraphicsNotice( ink_already_set );
  1016.     GXIgnoreGraphicsNotice( transform_already_set );    
  1017.     
  1018.     if( newstyle != nil )
  1019.         {
  1020.             overPtr->savestyle = GXCloneStyle( GXGetShapeStyle( sh ) );
  1021.             GXSetShapeStyle( sh, newstyle );
  1022.         }
  1023.  
  1024.     if( newink != nil )
  1025.         {
  1026.             overPtr->saveink = GXCloneInk( GXGetShapeInk( sh ) );
  1027.             GXSetShapeInk( sh, newink );
  1028.         }
  1029.     
  1030.     if( newtransform != nil )
  1031.         {
  1032.             overPtr->savetransform = GXCloneTransform( GXGetShapeTransform( sh ) );
  1033.             GXSetShapeTransform( sh, newtransform );
  1034.         }
  1035.  
  1036.     GXPopGraphicsNotice();
  1037.     GXPopGraphicsNotice();    
  1038.     GXPopGraphicsNotice();
  1039.  
  1040. }
  1041.  
  1042. /*-------------------------------------------------------------------------------
  1043.     
  1044.     TMRestoreOverrides
  1045.     
  1046.         this routine resets the shapes attributes (it undoes the work of the routine
  1047.         above).
  1048.  
  1049. -------------------------------------------------------------------------------*/
  1050.  
  1051. void TMRestoreOverrides( TTMShapeOverrides *overPtr )
  1052. {
  1053.     gxShape    sh = overPtr->sh;
  1054.     
  1055.     GXIgnoreGraphicsNotice( style_already_set );
  1056.     GXIgnoreGraphicsNotice( ink_already_set );
  1057.     GXIgnoreGraphicsNotice( transform_already_set );    
  1058.     
  1059.     if( overPtr->savestyle != nil )
  1060.         {
  1061.             GXSetShapeStyle( sh, overPtr->savestyle );
  1062.             GXDisposeStyle( overPtr->savestyle );
  1063.             overPtr->savestyle = nil;
  1064.         }
  1065.         
  1066.     if( overPtr->saveink != nil )
  1067.         {
  1068.             GXSetShapeInk( sh, overPtr->saveink );
  1069.             GXDisposeInk( overPtr->saveink );
  1070.             overPtr->saveink = nil;
  1071.         }
  1072.         
  1073.     if( overPtr->savetransform != nil )
  1074.         {
  1075.             GXSetShapeTransform( sh, overPtr->savetransform );
  1076.             GXDisposeTransform( overPtr->savetransform );
  1077.             overPtr->savetransform = nil;
  1078.         }    
  1079.     
  1080.     GXPopGraphicsNotice();
  1081.     GXPopGraphicsNotice();    
  1082.     GXPopGraphicsNotice();
  1083.  
  1084. }
  1085.  
  1086.  
  1087. /*-------------------------------------------------------------------------------
  1088.     
  1089.     TMConcatenateTransform
  1090.     
  1091.         this routine takes a transform and it concatenates it the the list.  this 
  1092.         function assumes that the stack has been initialized and that there is room
  1093.         for at least one entry
  1094.         
  1095.     returns
  1096.         any error returned by SetHandleSize();
  1097.  
  1098. -------------------------------------------------------------------------------*/
  1099. OSErr TMConcatenateTransform( TTransformList *trptr, gxTransform tr )
  1100. {
  1101.     OSErr status = noErr;
  1102.  
  1103.     gxShapeType shType;
  1104.     gxMapping        newtmap;
  1105.     long        tagcount;
  1106.     
  1107.     check( trptr->top <= trptr->mark );
  1108.     
  1109.     shType = GetTransformClipType( tr );
  1110.     tagcount = GXGetTransformTags( tr, 'post', 1, gxSelectToEnd, nil );
  1111.     
  1112.     GXGetTransformMapping( tr, &newtmap );
  1113.     
  1114.     trptr->seed +=  1;                    // bump the seed value so that we don't attach to this list
  1115.  
  1116.     // first we check to see if this is the first transform that we are adding to this list
  1117.     
  1118.     if( tagcount == 0 && TMTestIdentityMapping( &newtmap ) && shType == gxFullType )
  1119.         {
  1120.             trptr->seed -= 1;        // this transform is not worthy!
  1121.         }
  1122.     else
  1123.         {
  1124.             if( trptr->top == trptr->mark ) goto PushTransform;
  1125.             
  1126.             // if we are here then we know we have at least one more transform on the stack
  1127.             
  1128.             if( tagcount == 0 && trptr->cliptype == gxFullType )
  1129.                 {
  1130.                     gxTransform    toptr;
  1131.                     gxTransform newtr;
  1132.                     
  1133.                     gxMapping    curtmap;
  1134.  
  1135.                     newtr = GXNewTransform();
  1136.                     toptr = (* trptr->list)[ trptr->mark - 1 ];
  1137.                     
  1138.                     GXGetTransformMapping( toptr, &curtmap );
  1139.                     MapMapping( &newtmap, &curtmap );
  1140.                     
  1141.                     GXSetTransformMapping( newtr, &newtmap );
  1142.                     if( shType != gxFullType )
  1143.                         {
  1144.                             gxShape        sh = GXGetTransformClip( tr );
  1145.                             
  1146.                             GXSetTransformClip( newtr, sh );
  1147.                             trptr->cliptype = shType;
  1148.                             
  1149.                             GXDisposeShape( sh );
  1150.                         }
  1151.                     
  1152.                     (* trptr->list)[ trptr->mark - 1 ] = newtr;
  1153.                     GXDisposeTransform( toptr );
  1154.                 }
  1155.             else
  1156.                 {
  1157. PushTransform:                    
  1158.                     // we must push the new transform on the stack --
  1159.                     // we first make sure that the stack can hold it
  1160.                     
  1161.                     if( trptr->count <= trptr->mark )
  1162.                         {
  1163.                             // we need to grow the handle
  1164.                             
  1165.                             SetHandleSize((Handle) trptr->list, sizeof( gxTransform ) * 
  1166.                                                                                                     ( trptr->count + kStackListIncrement ) ); 
  1167.                             nrequire( status = MemError(), GrowHandleFailed );
  1168.  
  1169.                             trptr->count += kStackListIncrement;
  1170.                         }
  1171.                         
  1172.                     // by this point we are assured that we have enough room to push the transform
  1173.                     
  1174.                     if( tagcount )
  1175.                         (* trptr->list)[ trptr->mark ] = GXCloneTransform( tr );
  1176.                     else
  1177.                         (* trptr->list)[ trptr->mark ] = GXCopyToTransform( nil, tr );
  1178.                     
  1179.                     // and we increment the mark to show that we have a new transform 
  1180.                     
  1181.                     trptr->mark += 1;
  1182.                     
  1183.                     if( tagcount == 0 )
  1184.                         trptr->cliptype = shType;
  1185.                     else
  1186.                         trptr->cliptype = gxEmptyType;        // prevent further concatenation
  1187.                 }
  1188.         }
  1189.  
  1190. GrowHandleFailed:
  1191.  
  1192.     return( status );
  1193. }
  1194. /*-------------------------------------------------------------------------------
  1195.     
  1196.     TMInsertTMClip
  1197.     
  1198.         this routine inserts a transform at the top of the transform list.
  1199.  
  1200. -------------------------------------------------------------------------------*/
  1201. OSErr TMInsertTMClip( TTransformList *trptr, gxTransform tr )
  1202. {
  1203.     OSErr status = noErr;
  1204.     
  1205.     gxTransform        *aptr;
  1206.     gxTransform        *bptr;
  1207.     
  1208.     short    indx;
  1209.     
  1210.     check( trptr->top <= trptr->mark );
  1211.         
  1212.     // first we check to see if we have enough room to add the transform 
  1213.     
  1214.     if( trptr->count <= trptr->mark )
  1215.         {
  1216.             // we need to grow the handle 
  1217.             
  1218.             SetHandleSize((Handle) trptr->list, sizeof( gxTransform ) * 
  1219.                                                                                     ( trptr->count + kStackListIncrement ) );
  1220.             nrequire( status = MemError(), GrowStackFailed );            
  1221.             
  1222.             trptr->count += kStackListIncrement;
  1223.         }
  1224.         
  1225.     // to insert the transform we need to need to move down all of the other ones
  1226.  
  1227.     indx = trptr->mark - 1;                            // make the count zero based
  1228.  
  1229.     aptr = & (* trptr->list)[ indx ];        // the last transform on the list
  1230.     bptr = aptr + 1;
  1231.     
  1232.     indx -= trptr->top;                                    // only move the transforms above the top of the stack
  1233.     
  1234.     for( ; indx >= 0; --indx )
  1235.         {
  1236.             *bptr = *aptr;
  1237.             
  1238.             aptr -= 1;
  1239.             bptr -= 1;
  1240.         }
  1241.         
  1242.     (* trptr->list)[ trptr->top ] = tr;        // this is the transform that we had to insert
  1243.     
  1244.     trptr->top     += 1;
  1245.     trptr->mark    += 1;
  1246.     trptr->seed += 1;
  1247.  
  1248. GrowStackFailed:
  1249.     return( status );
  1250. }
  1251. /*-------------------------------------------------------------------------------
  1252.     
  1253.     TMRemoveTMClip
  1254.     
  1255.         this routine undoes the changes made by the one previously.  that is, it
  1256.         removes the transform from the top of the transform list.
  1257.  
  1258. -------------------------------------------------------------------------------*/
  1259. void TMRemoveTMClip( TTransformList *trptr )
  1260. {
  1261.     gxTransform        *aptr;
  1262.     gxTransform        *bptr;
  1263.     
  1264.     short    indx;
  1265.     
  1266.     #if DEBUGLEVEL>0
  1267.     
  1268.     if( trptr->top <= 0 )
  1269.         DebugStr( "\ptrptr->top is bad" );
  1270.  
  1271.     #endif
  1272.     
  1273.     GXDisposeTransform( (* trptr->list)[ trptr->top - 1 ] );
  1274.     
  1275.     aptr = & (* trptr->list)[ trptr->top - 1 ];
  1276.     bptr = aptr + 1;
  1277.     
  1278.     indx = trptr->mark - trptr->top;
  1279.     
  1280.     for( ; indx >= 0; --indx )
  1281.         {
  1282.             *aptr++ = *bptr++;
  1283.         }
  1284.         
  1285.     trptr->top -= 1;
  1286.     trptr->mark -= 1;
  1287. }
  1288. /*-------------------------------------------------------------------------------
  1289.     
  1290.     TMResolveShape
  1291.     
  1292.         given a parameter block as described below this routine process the next
  1293.         shape from the stack and returns it to the client so it can futz with it.
  1294.  
  1295. -------------------------------------------------------------------------------*/
  1296. OSErr TMResolveShape( TResolveParam *rpptr, Boolean doresolve )
  1297. {
  1298.     OSErr status = noErr;
  1299.     
  1300.     TRNABlock    rna;
  1301.     
  1302.     gxShape            sh;
  1303.     gxInk                shink;    
  1304.     gxColor            shcolor;
  1305.  
  1306.     gxShapeType    shType;
  1307.     gxInk                tmink;
  1308.     
  1309.     // the first thing that we do is grab the next available shape from the stack
  1310.     
  1311.     sh = TMNextShape( &( rpptr->stack ) );
  1312.     
  1313.     // before we add the new shape to the list we make sure that the strand is initialized
  1314.     
  1315.     rna.root = nil;        // initialize the picture strand
  1316.     rna.branch = nil;
  1317.     rna.node = nil;
  1318.     rna.seed = 0;            // initialize the transform list seed
  1319.     
  1320.     rna.rootst = nil;
  1321.     rna.roottm = nil;
  1322.     rna.roottr = nil;
  1323.     
  1324.     if( sh != nil )
  1325.         {
  1326.             short        iscopymode;
  1327.             
  1328.             shType = GXGetShapeType( sh );
  1329.             
  1330.             // now that we have a shape we need to figure out what the color that this shape will have
  1331.             // is if it where to render alone on a 'blank' frame buffer.  to do this we start by setting
  1332.             // the variable shcolor to white [ /gray 1.0 ] and then combining the color contained
  1333.             // in the ink to using the transfer mode that the ink contains.  once we have the 
  1334.             // correct color  we make a new ink and set the color of that ink to be the result of 
  1335.             // the combination.
  1336.             
  1337.             // now we get the bounds of the shape -- we always do this transfer modes or not
  1338.             
  1339.             TMGetShapeBounds( &( rpptr->shbbox ), sh, &( rpptr->stack ), &( rpptr->bp ) );
  1340.             
  1341.             // and we check to see if we have a transfer mode
  1342.             
  1343.             shink = GXGetShapeInk( sh );
  1344.             
  1345.             if( doresolve )
  1346.                 iscopymode = TMTestCopyMode( shink );
  1347.             else
  1348.                 iscopymode = true;        // treat all shapes as if they had copy mode
  1349.             
  1350.             if( shType == gxBitmapType )
  1351.                 {
  1352.                     gxShape        sh2;
  1353.                     gxBitmap    thebits;
  1354.                     
  1355.                     // we have a bitmap shape -- oh God! -- what to do.  when we have a bitmap it
  1356.                     // draws on top of all of the shapes that it overlaps. to reproduce this effect
  1357.                     // we need to create an offscreen and draw all of the previous shapes into it
  1358.                     // and then draw the bitmap itself -- we ignore any transfer mode information
  1359.                     // while rendering all of the shapes into the bitmap as these will be resolved
  1360.                     // naturaly.
  1361.                     
  1362.                     if( ! iscopymode )
  1363.                         {
  1364.                             // one last chance to be in copy mode is if the bitmap is in or mode
  1365.                             
  1366.                             (void) GXGetBitmap( sh, &thebits, nil );
  1367.                             if( thebits.pixelSize == 1 )
  1368.                                 {
  1369.                                     if( ( iscopymode = TMTestOrMode( shink ) ) || 
  1370.                                             ( iscopymode = TMTestMinMode( shink ) ) )
  1371.                                         {
  1372.                                             // we have to set a clip on this shape which corresponds to 
  1373.                                             // bits that the user wants to or on the screen
  1374.                                             
  1375.                                             sh2 = TMResolveOrModeBitmap( sh );
  1376.                                             TMAttachShape( &rna, sh2, nil, &( rpptr->stack ) );
  1377.                                             
  1378.                                             goto relaseClone;
  1379.                                         }
  1380.                                 }
  1381.                             else
  1382.                                 {
  1383.                                     // check to see if the shape is transparent anyway
  1384.                                     
  1385.                                     if( ! (iscopymode = TMTestOrMode( shink ) ) ) iscopymode = TMTestMinMode( shink );
  1386.                                 }
  1387.                         }
  1388.                     
  1389.                     if( ! iscopymode )                            // if the bitmap is blitted with a transfer mode
  1390.                         {
  1391.                             if( rpptr->stack.index == 1 )            // if this is the first shape then this is all
  1392.                                 {
  1393.                                     sh2 = TMCombineBitmapColors( sh, shink, nil, nil, nil );
  1394.                                     TMAttachShape( &rna, sh2, nil, &( rpptr->stack ) );
  1395.                                 }
  1396.                             else
  1397.                                 {
  1398.                                     // we make a shape where all of the shapes are re-rendered into the bitmap
  1399.                                     
  1400.                                     sh2 = TMResolveBitmap( & rpptr->stack, nil, &( rpptr->shbbox ) );
  1401.                                     TMAttachShapeSimple( &rna, sh2, & rpptr->stack );
  1402.                                     
  1403.                                     // make sure that we don't re-do this below
  1404.                                     iscopymode = true;
  1405.                                 }
  1406.                         }
  1407.                     else
  1408.                         {
  1409.                             sh2 = GXCloneShape( sh );
  1410.                             TMAttachShape( &rna, sh2, nil, &( rpptr->stack ) );
  1411.                         }
  1412. relaseClone:                    
  1413.                     GXDisposeShape( sh2 );                // balance the oc
  1414.                     
  1415.                     // check to see if we are done or if we need too
  1416.                 }
  1417.             else
  1418.                 {
  1419.                     // if we have a single colored shape and the transfer mode on it is orMode 
  1420.                     // (in gx graphics implemented as a flavor of the copy code) then we don't need to
  1421.                     // resolve it but we still need to change the 
  1422.                                         
  1423.                     // if we still have a transfer mode then we have to do something drastic
  1424.                     
  1425.                     if( iscopymode == false )
  1426.                         {
  1427.                             TMCombineColors( &shcolor, shink, nil );                            
  1428.                             GXSetInkColor( tmink = GXNewInk(), &shcolor );
  1429.                             
  1430.                             if( ! iscopymode ) iscopymode = TMTestOrMode( shink );
  1431.                         }
  1432.                     else
  1433.                         {
  1434.                             // we don't have a transfer mode and we need to give this shape the
  1435.                             // overriding ink that i had originally when we pulled it out of the picture
  1436.                             
  1437.                             if( rpptr->stack.newink )
  1438.                                 tmink = GXCloneInk( shink );
  1439.                             else
  1440.                                 tmink = nil;                    // leave the shape with it's original ink
  1441.                         }
  1442.                     
  1443.                     // by this point the 'correct' color for this shape is contained in shcolor and an ink
  1444.                     // in the variable tmink.  the next step is to start a picture for this shape.  this is
  1445.                     // accomplished by means of the rna structure.  for those familiar with the biological
  1446.                     // processes at the molecular level (MIT 7.01) rna is the molecular entity that is 
  1447.                     // responsible for building up proteins in the cells citoplasm.  this action is acomplished
  1448.                     // by transcribing a series of aminoacid sequences one atom at the time.  similarly the 
  1449.                     // rna data structure serves to build up the picture of the 'resolved' shape one shape
  1450.                     // at the time.  every time that we have a new shape that we need to add to the 
  1451.                     // picture 'strand' we call TMAttachShape() and pass it to it.  to begin we set the
  1452.                     // rna.root shape to be nil and at the end we can extract out finished shape from 
  1453.                     // rna.root using the rna.rootm and rna.roottr as the overriding ink and transforms for it.
  1454.                                 
  1455.                     TMAttachShape( &rna, sh, tmink, &( rpptr->stack ) );        // and attach the shape
  1456.                     if( tmink ) GXDisposeInk( tmink );                                            // we no longer own this
  1457.                 }
  1458.                     
  1459.             // check to see if we have a transfer mode 
  1460.             
  1461.             if( ( iscopymode == false ) && ( 1 < rpptr->stack.index ) )
  1462.                 {    
  1463.                     TTModeStack    stack;        // this is the transfer mode stack
  1464.                     gxRectangle        shbbox;
  1465.                 
  1466.                     // if we are inside this loop this means that we have a transfer mode to resolve.
  1467.                     // we make a new stack in which we can keep the transfer mode information.
  1468.  
  1469.                     nrequire( status = TMNewTModeStack( &stack ), MakeTMStackFailed );
  1470.                     nrequire( status = TMPushTMBlock( &stack, sh, &( rpptr->shbbox ), 
  1471.                                                                                                                 &( rpptr->stack ) ), 
  1472.                                                 FirstPushBlockFailed );
  1473.                     
  1474.                     TMFreeShape( &( rpptr->stack ) );                // we release the shape
  1475.                     TMRewindStack( &( rpptr->stack ) );            // and rewind the stack
  1476.                     
  1477.                     // this is where all the work goes on
  1478.  
  1479.                     for(;;)
  1480.                         {
  1481.                             long        indx;
  1482.                             long        count;
  1483.                             
  1484.                             gxRectangle    sh2bbox;
  1485.                             
  1486.                             gxShape            sh2;
  1487.                             gxInk                sh2ink;
  1488.                             gxColor            sh2color;
  1489.                             
  1490.                             gxInk                tm2ink;
  1491.                                                                                                     
  1492.                             sh2 = TMNextShape( &( rpptr->stack ) );
  1493.  
  1494.                             TMPeekTMBlock( &indx, &count, &shbbox, &stack );
  1495.  
  1496.                             if( indx < count )
  1497.                                 {
  1498.                                     TMBumpTMBlock( &stack, &rpptr->stack );    // this bumps the mark in the field                                            
  1499.                                     TMGetShapeBounds( &sh2bbox, sh2, &( rpptr->stack ), &( rpptr->bp ) );
  1500.                                     
  1501.                                     // see if these two shapes intersect
  1502.                                     
  1503.                                     if( GXIntersectRectangle( &sh2bbox, &sh2bbox, &shbbox ) 
  1504.                                         && ( ! emptyrectangle( &sh2bbox ) ) )
  1505.                                         {
  1506.                                             gxShapeType sh2Type = GXGetShapeType( sh2 );
  1507.                                             
  1508.                                             // we have a shape that intersects -- ho ho ho
  1509.                                             
  1510.                                             iscopymode = TMTestCopyMode( sh2ink = GXGetShapeInk( sh2 ) );
  1511.                                             
  1512.                                             // we need to run this shape through all of the inks in the stack
  1513.                                             
  1514.                                             if( sh2Type != gxBitmapType )
  1515.                                                 {
  1516.                                                     TMCombineColors( &sh2color, sh2ink, &stack );
  1517.                                                     GXSetInkColor( tm2ink = GXNewInk(), &sh2color );
  1518.                                                     TMAttachShape( &rna, sh2, tm2ink, &( rpptr->stack ) );
  1519.                                                     
  1520.                                                     GXDisposeInk( tm2ink );        // we are done with this
  1521.                                                     
  1522.                                                     // see if the shape has a transfer mode of its own
  1523.                                                     
  1524.                                                     if( ( 1 < indx ) && ( iscopymode == false ) )
  1525.                                                         {
  1526.                                                             nrequire( status = TMPushTMBlock( &stack, sh2, &sh2bbox, 
  1527.                                                                                                                                 &( rpptr->stack ) ), PushBlockFailed );
  1528.                                                             
  1529.                                                             TMFreeShape( &( rpptr->stack ) );
  1530.                                                             TMRewindStack( &( rpptr->stack ) );
  1531.                                                         }
  1532.                                                     else
  1533.                                                         {
  1534.                                                             TMFreeShape( &( rpptr->stack ) );
  1535.                                                         }
  1536.                                                 }
  1537.                                             else
  1538.                                                 {
  1539.                                                     if( iscopymode != false )
  1540.                                                         {
  1541.                                                             sh2 = TMCombineBitmapColors( sh2, sh2ink, &stack, &sh2bbox, &( rpptr->stack.tr ) );
  1542.                                                             TMAttachShape( &rna, sh2, nil, &( rpptr->stack ) );
  1543.                                                         }
  1544.                                                     else
  1545.                                                         {
  1546.                                                             sh2 = TMResolveBitmap( &rpptr->stack, &stack, &sh2bbox );
  1547.                                                             TMAttachShapeSimple( &rna, sh2, &rpptr->stack );
  1548.                                                         }
  1549.  
  1550.                                                     GXDisposeShape( sh2 );
  1551.                                                     TMFreeShape( &( rpptr->stack ) );
  1552.                                                 }
  1553.                                         }
  1554.                                     else
  1555.                                         {
  1556.                                             TMFreeShape( &( rpptr->stack ) );
  1557.                                         }
  1558.                                 }
  1559.                             else
  1560.                                 {
  1561.                                     TMPopTMBlock( &stack, &( rpptr->stack ) );
  1562.                                     
  1563.                                     // we should not release the shape that we have when we terminate
  1564.                                     // because the client will take care of that.  
  1565.                                     
  1566.                                     if( ! emptystackq( &stack ) )
  1567.                                         TMFreeShape( &( rpptr->stack ) );
  1568.                                     else
  1569.                                         break;
  1570.                                 }
  1571.                         } 
  1572.                                                         
  1573. FirstPushBlockFailed:                    
  1574. PushBlockFailed:
  1575.                     
  1576.                     check( rpptr->stack.tr.top == 0 );
  1577.                     
  1578.                     TMDisposeTModeStack( &stack );
  1579.                     
  1580.                 }            
  1581.         }
  1582.     
  1583.     // at this point we are all done.  our product is the root of the rna strand.
  1584.     // also, since we took either one of the two paths we have now returned the 
  1585.     // shape to the 'grabbed' state.  the shape is freed at the release shape call
  1586.     
  1587.     rpptr->sh = ( rna.root == nil ) ? rna.node : rna.root;
  1588.     rpptr->st = rna.rootst;
  1589.     rpptr->tm = rna.roottm;
  1590.     rpptr->tr = rna.roottr;    
  1591.     
  1592. MakeTMStackFailed:
  1593. PushShapeFailed:
  1594.     return( status );
  1595. }
  1596. /*-------------------------------------------------------------------------------
  1597.     
  1598.     TMReleaseShape
  1599.     
  1600.         this call lets the resolver know that the client is done with this shape.
  1601.  
  1602. -------------------------------------------------------------------------------*/
  1603. void TMReleaseShape( TResolveParam *rpptr )
  1604. {
  1605.     check( rpptr->sh );
  1606.     
  1607.     GXDisposeShape( rpptr->sh );                                // balance the owner count of everyting
  1608.  
  1609.     if( rpptr->st != nil ) GXDisposeStyle( rpptr->st );
  1610.     if( rpptr->tm != nil ) GXDisposeInk( rpptr->tm );
  1611.     if( rpptr->tr != nil ) GXDisposeTransform( rpptr->tr );
  1612.  
  1613.     TMFreeShape( &( rpptr->stack ) );
  1614. }
  1615. /*-------------------------------------------------------------------------------
  1616.     
  1617.     TMAttachShape
  1618.     
  1619.         this call attaches a shape to an RNA strand 
  1620.  
  1621. -------------------------------------------------------------------------------*/
  1622. void TMAttachShape( TRNABlock *rnaptr, gxShape sh, gxInk tm, TShapeStack *stackPtr )
  1623. {
  1624.     gxStyle            shstyle;
  1625.     gxInk                shink;
  1626.     gxTransform    shtransform;
  1627.     
  1628.     short             indx;
  1629.     gxTransform    *trptr;
  1630.     
  1631.     short        clipflag = false;
  1632.         
  1633.     // set the shapes up
  1634.     
  1635.     if( sh == stackPtr->sh )
  1636.         {
  1637.             shstyle = stackPtr->newstyle;
  1638.             shtransform = stackPtr->newtransform;
  1639.             if( tm ) shink = tm; else shink = stackPtr->newink;
  1640.         }
  1641.     else
  1642.         {
  1643.             shstyle = nil;
  1644.             shink = tm;
  1645.             shtransform = nil;
  1646.         }
  1647.  
  1648.     sh = GXCloneShape( sh );
  1649.  
  1650.     if( shstyle != nil )            GXCloneStyle( shstyle );
  1651.     if( shink != nil )                GXCloneInk( shink );
  1652.     if( shtransform != nil )    GXCloneTransform( shtransform );
  1653.             
  1654.     // check to see if the seed that we have is the same as the one in the
  1655.     // stack pointer tr list.  if they are then we add to the node and not to the root
  1656.     // note: a rnaptr->seed of 0 means that it is unitialized as stackPtr->tr.seed cannot == 0
  1657.  
  1658.     if( ( rnaptr->seed != stackPtr->tr.seed ) || ( rnaptr->branch == nil ) )
  1659.         {                
  1660.             indx = stackPtr->tr.mark - 1;            // this is the index for the top transform on the stack
  1661.             trptr = & (* stackPtr->tr.list)[ indx ];
  1662.         
  1663.             if( 0 <= indx )            // if there are more transforms still we DO need a picture
  1664.                 {
  1665.                     gxShape sh2;
  1666.                     
  1667.                     sh2 = GXNewPicture( 1, &sh, &shstyle, &shink, &shtransform );
  1668.                     
  1669.                     GXDisposeShape( sh );
  1670.         
  1671.                     if( shstyle != nil )            { GXDisposeStyle( shstyle );                     shstyle = nil;             }
  1672.                     if( shink != nil )                { GXDisposeInk( shink );                            shink = nil;                 }
  1673.                     if( shtransform != nil )    { GXDisposeTransform( shtransform );    shtransform = nil;    }        
  1674.                     
  1675.                     // this picture now can become the node to which other shapes can be added to
  1676.                     // as long and the seed value in rna and stackPtr->tr remains the same
  1677.                     
  1678.                     rnaptr->branch = sh2;
  1679.                     
  1680.                     sh = sh2;
  1681.                     
  1682.                     GXSetShapeTransform( sh, *trptr );            
  1683.                     
  1684.                     indx -= 1;
  1685.                     trptr -= 1;
  1686.                 }
  1687.                 
  1688.             for( ; indx >= 0 ; --indx )
  1689.                 {
  1690.                     gxShape sh2;
  1691.                     
  1692.                     sh2 = GXNewPicture( 1, &sh, nil, nil, nil );
  1693.                     
  1694.                     GXDisposeShape( sh );
  1695.                                 
  1696.                     sh = sh2;
  1697.                     
  1698.                     GXSetShapeTransform( sh, *trptr );
  1699.                     
  1700.                     trptr -= 1;
  1701.                 }
  1702.                 
  1703.             // here we have a shape suitable for being appended to the list
  1704.             
  1705.             if( ( rnaptr->root == nil ) && ( rnaptr->node == nil ) )
  1706.                 {
  1707.                     rnaptr->node = GXCloneShape( sh );
  1708.                     
  1709.                     if( shstyle != nil )            GXCloneStyle( shstyle );                    rnaptr->rootst = shstyle;
  1710.                     if( shink != nil )                 GXCloneInk( shink );                             rnaptr->roottm = shink;
  1711.                     if( shtransform != nil )    GXCloneTransform( shtransform );     rnaptr->roottr = shtransform;
  1712.                 }
  1713.             else 
  1714.                 {
  1715.                     if( rnaptr->root == nil )
  1716.                         {
  1717.                             rnaptr->root = GXNewPicture( 1, &rnaptr->node, &rnaptr->rootst, 
  1718.                                                                                         &rnaptr->roottm, &rnaptr->roottr );
  1719.                             GXDisposeShape( rnaptr->node );
  1720.                             
  1721.                             // the only time that we want to replace the brach here is if there is 
  1722.                             // no root and no branch.  if there is a node but no root the branch, if 
  1723.                             // set, is correct.  if the branch is not set then it is the same as
  1724.                             // the root because the node is not a picture
  1725.                             
  1726.                             if( rnaptr->branch == nil )
  1727.                                 rnaptr->branch = rnaptr->root;
  1728.                             
  1729.                             if( rnaptr->rootst != nil )    { GXDisposeStyle( rnaptr->rootst );         rnaptr->rootst = nil; }
  1730.                             if( rnaptr->roottm != nil )    { GXDisposeInk( rnaptr->roottm );                rnaptr->roottm = nil; }
  1731.                             if( rnaptr->roottr != nil ) { GXDisposeTransform( rnaptr->roottr );    rnaptr->roottr = nil;    }        
  1732.                         }
  1733.                                 
  1734.                     GXSetPictureParts( rnaptr->root, 0, 0, 1, &sh, &shstyle, &shink, &shtransform );
  1735.                 }
  1736.         }
  1737.     else
  1738.         {
  1739.             check( rnaptr->branch != nil );
  1740.             
  1741.             // the seed values are equal so we add the shape to the branch instead
  1742.             
  1743.             GXSetPictureParts( rnaptr->branch, 0, 0, 1, &sh, &shstyle, &shink, &shtransform );
  1744.         }
  1745.  
  1746.     GXDisposeShape( sh );
  1747.     
  1748.     if( shstyle != nil )            GXDisposeStyle( shstyle );
  1749.     if( shink != nil )                GXDisposeInk( shink );
  1750.     if( shtransform != nil )    GXDisposeTransform( shtransform );
  1751.     
  1752.     rnaptr->seed = stackPtr->tr.seed;
  1753.  
  1754. }
  1755.  
  1756. /*-------------------------------------------------------------------------------
  1757.     
  1758.     TMAttachShapeSimple
  1759.     
  1760.         this routine attaches a shape to a strand so that it is at the top most
  1761.         level.  it also nukes the transform seed preventing any more shapes from
  1762.         being added to the branch of the block.
  1763.         
  1764. -------------------------------------------------------------------------------*/
  1765.  
  1766. void TMAttachShapeSimple( TRNABlock *rnaptr, gxShape sh, TShapeStack *stackPtr )
  1767. {
  1768.     TTransformList    *listPtr = &stackPtr->tr;
  1769.     
  1770.     // first we need to concatenate this with all of the clips that are on the stack
  1771.     
  1772.     if( 0 < listPtr->top )
  1773.         {
  1774.             short                 indx;
  1775.             gxTransform        *trptr;
  1776.  
  1777.             // this means that we have clips that we need to attach to this shape
  1778.             
  1779.             HLock((Handle) listPtr->list );
  1780.             
  1781.             trptr = & (* listPtr->list)[ listPtr->top -1 ];
  1782.             
  1783.             GXSetShapeTransform( sh, *trptr-- );
  1784.             
  1785.             indx = listPtr->top - 2;            // -1 for zero base and -1 for the one we did already
  1786.             
  1787.             if( 0 < indx )
  1788.                 {
  1789.                     
  1790.                     for( ; indx >= 0; --indx )
  1791.                         {
  1792.                             sh = GXNewPicture( 1,  &sh, nil, nil, nil );
  1793.                             
  1794.                             GXSetShapeTransform( sh, *trptr-- );
  1795.                         }
  1796.                 }
  1797.             
  1798.             HUnlock((Handle) listPtr->list );
  1799.         }
  1800.     
  1801.     // check to see if the root node is not nil
  1802.     
  1803.     if( ( rnaptr->node == nil ) && ( rnaptr->root == nil ) )
  1804.         {
  1805.             // this is the first shape on the strand
  1806.             
  1807.             rnaptr->root = GXNewPicture( 1, &sh, nil, nil, nil );
  1808.             
  1809.             rnaptr->rootst = nil;
  1810.             rnaptr->roottm = nil;
  1811.             rnaptr->roottr = nil;
  1812.         }
  1813.     else
  1814.         {
  1815.             if( rnaptr->root == nil )
  1816.                 {
  1817.                     rnaptr->root = GXNewPicture( 1, &rnaptr->node, &rnaptr->rootst, 
  1818.                                                                                 &rnaptr->roottm, &rnaptr->roottr );
  1819.                     GXDisposeShape( rnaptr->node );
  1820.                     
  1821.                     if( rnaptr->rootst != nil )    { GXDisposeStyle( rnaptr->rootst );         rnaptr->rootst = nil; }
  1822.                     if( rnaptr->roottm != nil )    { GXDisposeInk( rnaptr->roottm );                rnaptr->roottm = nil; }
  1823.                     if( rnaptr->roottr != nil ) { GXDisposeTransform( rnaptr->roottr );    rnaptr->roottr = nil;    }        
  1824.                 }
  1825.             
  1826.             GXSetPictureParts( rnaptr->root, 0, 0, 1, &sh, nil, nil, nil );
  1827.         }
  1828.         
  1829.     rnaptr->seed = 0;        // make sure that all further shapes are added to the root
  1830. }
  1831.  
  1832. /*-------------------------------------------------------------------------------
  1833.     
  1834.     TMTestOrMode
  1835.     
  1836.         this call checks to see if the transfer mode for an ink is something other
  1837.         than copy.  it also check and fixes up any transfer mode that is xor and 
  1838.         pixel xor.
  1839.  
  1840. -------------------------------------------------------------------------------*/
  1841. Boolean TMTestOrMode( gxInk shink )
  1842. {
  1843.     gxTransferMode    shmode;
  1844.     
  1845.     Boolean        result;
  1846.     
  1847.     short    count;
  1848.         
  1849.     result = true;        // assume that the transfer mode is or    
  1850.  
  1851.     GXGetInkTransfer( shink, &shmode );
  1852.     
  1853.     if( count = TMGetSpaceComponentCount( shmode.space ) )
  1854.         {
  1855.             gxTransferComponent        *trc = shmode.component;
  1856.  
  1857.             do
  1858.                 {
  1859.                     // there are two possible representations of or mode
  1860.                     // one is gxCopy mode where ->sourceMinimum == ->sourceMaximum
  1861.                     // and the other is
  1862.                     // gxMinimum and ->sourceMinimum == 0 and ->sourceMaximum == 0xFFFF
  1863.                 
  1864.                     if( ( trc->mode == gxCopyMode &&
  1865.                                 trc->sourceMinimum == trc->sourceMaximum ) )
  1866.                         {
  1867.                             // do nothing; we have what we want
  1868.                         }
  1869.                     else
  1870.                         {
  1871.                             result = false;
  1872.                             break;
  1873.                         }
  1874.                     
  1875.                     trc += 1;
  1876.  
  1877.                 } while( 0 < --count );
  1878.         }
  1879.  
  1880.     return( result );
  1881.  
  1882. }
  1883.  
  1884. /*-------------------------------------------------------------------------------
  1885.     
  1886.     TMTestCopyMode
  1887.     
  1888.         this call checks to see if the transfer mode for an ink is something other
  1889.         than copy.  it also check and fixes up any transfer mode that is xor and 
  1890.         pixel xor.
  1891.  
  1892. -------------------------------------------------------------------------------*/
  1893. Boolean TMTestCopyMode( gxInk shink )
  1894. {
  1895.     gxTransferMode    shmode;
  1896.     
  1897.     Boolean        result;
  1898.     
  1899.     short    indx;
  1900.     short    count;
  1901.     
  1902.     gxTransferComponent        *trComponent;
  1903.     
  1904.     GXGetInkTransfer( shink, &shmode );
  1905.  
  1906.     count = TMGetSpaceComponentCount( shmode.space );
  1907.  
  1908.     // if we are replicating the same component the only check the first one
  1909.     
  1910.     if( count && ( shmode.flags & gxSingleComponentTransfer ) ) count = 1;
  1911.     
  1912.     result = true;        // assume that the transfer mode is copy
  1913.     
  1914.     trComponent = shmode.component;
  1915.     for( indx = 0; indx < count; ++indx )
  1916.         {
  1917.             
  1918.             if (    (trComponent->mode != gxCopyMode)                    ||
  1919.                         (trComponent->sourceMinimum != 0x0000)    ||
  1920.                         (trComponent->sourceMaximum != 0xFFFF)    ||
  1921.                         (trComponent->deviceMinimum != 0x0000)    ||
  1922.                         (trComponent->deviceMaximum != 0xFFFF)    ||
  1923.                         (trComponent->clampMinimum != 0x0000)        ||
  1924.                         (trComponent->clampMaximum != 0xFFFF)
  1925.                     )
  1926.                 {
  1927.                     result = false;
  1928.                     break;
  1929.                 }
  1930.                 
  1931.             ++trComponent;
  1932.         }
  1933.  
  1934.     return( result );
  1935.  
  1936. }
  1937. /*-------------------------------------------------------------------------------
  1938.     
  1939.     TMTestComponentMode
  1940.     
  1941.         this call checks to see if the component for a transfer mode is the given one.
  1942.  
  1943. -------------------------------------------------------------------------------*/
  1944.  
  1945. Boolean TMTestComponentMode( gxTransferComponent *component, unsigned char mode )
  1946. {
  1947.     if( ( component->mode == mode )                &&
  1948.             ( component->deviceMinimum == 0 )                                &&
  1949.             ( component->clampMinimum == 0 )                                &&
  1950.             ( component->deviceMaximum == 0xFFFF )                    &&
  1951.             ( component->clampMaximum == 0xFFFF ) )
  1952.         return( true );
  1953.     else
  1954.         return( false );
  1955. }
  1956.  
  1957. /*----------------------------------------------------------------------------------
  1958.  
  1959.     TMGetSpaceComponentCount
  1960.     
  1961.         this routine returns the number of components for a color space.
  1962.                                                 
  1963. ----------------------------------------------------------------------------------*/
  1964. short TMGetSpaceComponentCount( gxColorSpace    space )
  1965. {
  1966.     short        count;
  1967.     
  1968.     switch( space )
  1969.         {
  1970.             case gxRGBSpace:
  1971.             case gxHSVSpace:
  1972.             case gxHLSSpace:
  1973.             case gxYXYSpace:
  1974.             case gxXYZSpace:
  1975.             case gxLUVSpace:
  1976.             case gxLABSpace:
  1977.             case gxYIQSpace:
  1978.             case gxRGB16Space:
  1979.             case gxRGB32Space:
  1980.             case gxHSV32Space:
  1981.             case gxHLS32Space:
  1982.             case gxYXY32Space:
  1983.             case gxXYZ32Space:
  1984.             case gxLUV32Space:
  1985.             case gxLAB32Space:
  1986.             case gxYIQ32Space:
  1987.                 count = 3;
  1988.                 break;
  1989.             
  1990.             case gxRGBASpace:
  1991.             case gxCMYKSpace:
  1992.             case gxARGB32Space:
  1993.             case gxCMYK32Space:
  1994.                 count = 4;
  1995.                 break;
  1996.             
  1997.                 
  1998.             case gxGraySpace:
  1999.             case gxIndexedSpace:
  2000.                 count = 1;
  2001.                 break;
  2002.             
  2003.             case gxGrayASpace:
  2004.                 count = 2;
  2005.                 break;
  2006.             
  2007.             default:
  2008.                 count = 0;
  2009.                 break;
  2010.  
  2011.             }
  2012.         
  2013.     return( count );
  2014. }
  2015. /*----------------------------------------------------------------------------------
  2016.  
  2017.     TMNewTModeStack
  2018.     
  2019.         this routine returns the number of components for a color space.
  2020.                                                 
  2021. ----------------------------------------------------------------------------------*/
  2022.  
  2023. OSErr TMNewTModeStack( TTModeStack *stackPtr )
  2024. {
  2025.     OSErr status;
  2026.  
  2027.     stackPtr->stack = (TTModeBlock **) NewHandle( kStackListIncrement * sizeof( TTModeBlock ) );
  2028.     nrequire( status = MemError(), MakeStackFailed );
  2029.     
  2030.     stackPtr->mark = 0;
  2031.     stackPtr->count = kStackListIncrement;
  2032.     
  2033. MakeStackFailed:
  2034.     return( status );
  2035. }
  2036.  
  2037. /*----------------------------------------------------------------------------------
  2038.  
  2039.     TMDisposeTModeStack
  2040.     
  2041.         this routine gets rid of a TMode stack.
  2042.                                                 
  2043. ----------------------------------------------------------------------------------*/
  2044. void TMDisposeTModeStack( TTModeStack *stackPtr )
  2045. {
  2046.     check( stackPtr->mark == 0 );
  2047.     
  2048.     DisposeHandle((Handle) stackPtr->stack );
  2049.     ncheck( MemError() );
  2050.     
  2051.     stackPtr->count = 0;
  2052. }
  2053. /*----------------------------------------------------------------------------------
  2054.  
  2055.     TMPushTMBlock
  2056.     
  2057.         this routine concatenates the information needed to render concatenated 
  2058.         transfer modes.
  2059.                                                 
  2060. ----------------------------------------------------------------------------------*/
  2061. OSErr TMPushTMBlock( TTModeStack *stackPtr, 
  2062.                                          gxShape                 sh, 
  2063.                                          gxRectangle      *shbboxptr, 
  2064.                                          TShapeStack *shstackPtr )
  2065. {
  2066.     OSErr status;
  2067.  
  2068.     gxShape     clipshape;
  2069.     
  2070.     gxTransform        xform;
  2071.     gxMapping            newmap;
  2072.     
  2073.     TTModeBlock     *blockPtr;
  2074.     
  2075.     #if DEBUGLEVEL>0
  2076.     
  2077.     if( shstackPtr->index <= 1 )
  2078.         DebugStr( "\pthere are no shapes to push in TMPushTMBlock" );
  2079.  
  2080.     if( shstackPtr->tr.mark < shstackPtr->tr.top )
  2081.         DebugStr( "\pTM stack overflow in TMPushTMBlock" );
  2082.         
  2083.     #endif
  2084.         
  2085.     // now we make a new transform and assign to it the mapped shape
  2086.     
  2087.     xform = GXNewTransform();                
  2088.  
  2089.     // the code below figures out the new clip for the shape that is being pushed on the stack.
  2090.         
  2091.     {
  2092.         gxShape            otherclip = GXGetShapeClip( sh );
  2093.  
  2094.         gxShapeType shType = GXGetShapeType( sh );
  2095.         
  2096.         if( ( shType == gxTextType ) || ( shType == gxGlyphType ) || ( shType == gxLayoutType ) )
  2097.             {
  2098.  
  2099. #if !defined( GraphicsLab ) && !defined( GraphicsScript)
  2100.                 nrequire( status = TextToUnhintedPath( clipshape = GXCopyToShape( nil, sh ) ), TextToPathFailed);
  2101. #else
  2102.                 GXSetShapeType( clipshape = GXCopyToShape( nil, sh ), gxPathType );
  2103. #endif
  2104.  
  2105.             }
  2106.         else
  2107.             {
  2108.                 GXPrimitiveShape( clipshape = GXCopyToShape( nil, sh ) );    
  2109.             }
  2110.  
  2111.         // ## bug number #1202310 -- transfer modes and lighting draw
  2112.         // sometimes shapes have the gxMapTransform attribute set.  this causes the later
  2113.         // invocation of the MapShape call to do nothing and gives us the wrong clip
  2114.         
  2115.         GXSetShapeAttributes( clipshape, GXGetShapeAttributes( clipshape ) & ~gxMapTransformShape );
  2116.         
  2117.         // concatenate the clip we calculated with the shapes clip
  2118.         
  2119.         GXIntersectShape( clipshape, otherclip );
  2120.  
  2121.         // get the concatenated mapping which will take us to device space and map the clip 
  2122.         
  2123.         if( TMGetDeviceMapping( &newmap, sh, & shstackPtr->tr ) )
  2124.             {
  2125.                 GXMapShape( clipshape, &newmap );
  2126.             }
  2127.         
  2128.         GXDisposeShape( otherclip );
  2129.     }
  2130.  
  2131.     GXSetTransformClip( xform, clipshape );
  2132.     GXDisposeShape( clipshape );
  2133.  
  2134.     check( GXGetTransformOwners( xform ) == 1 );
  2135.     
  2136.     nrequire( status = TMInsertTMClip( &( shstackPtr->tr), xform ), InsertClipFailed );
  2137.     
  2138.     // now we do the ink -- first we make sure that we have enough room to put in a new block
  2139.     
  2140.     if( stackPtr->count <= stackPtr->mark )
  2141.         {
  2142.             // we need to grow the stack
  2143.             
  2144.             SetHandleSize((Handle) stackPtr->stack, sizeof( TTModeBlock ) *
  2145.                                                                                             ( stackPtr->count + kStackListIncrement ) );
  2146.             nrequire( status = MemError(), GrowStackFailed );
  2147.             
  2148.             stackPtr->count += kStackListIncrement;
  2149.         }
  2150.     
  2151.     blockPtr = & (* stackPtr->stack)[ stackPtr->mark ];        // the next available space
  2152.     
  2153.     check( 1 < shstackPtr->index );
  2154.     
  2155.     blockPtr->mark = 1;                                                // this is the index of the shape that we start at
  2156.     blockPtr->count = shstackPtr->index;            // this is the index of ths shape that we are
  2157.     
  2158.     check( blockPtr->mark < blockPtr->count );
  2159.     
  2160.     blockPtr->tm = GXCloneInk( GXGetShapeInk( sh ) );
  2161.     blockPtr->shbbox = *shbboxptr;
  2162.     blockPtr->sh = GXCloneShape( sh );
  2163.     
  2164.     // we now bump the mark
  2165.     
  2166.  stackPtr->mark += 1;
  2167.  
  2168. TextToPathFailed:
  2169. GrowStackFailed:
  2170. InsertClipFailed:
  2171.  
  2172.     return( status );
  2173. }
  2174. /*----------------------------------------------------------------------------------
  2175.  
  2176.     TMPopTMBlock
  2177.     
  2178.         this routine pops the topmost block from the transfer mode list.
  2179.                                                 
  2180. ----------------------------------------------------------------------------------*/
  2181. void TMPopTMBlock( TTModeStack *stackPtr, TShapeStack *shstackPtr )
  2182. {
  2183.     TTModeBlock     *blockPtr;
  2184.  
  2185.     check( 0 < stackPtr->mark );
  2186.     
  2187.     #if DEBUGLEVEL>0
  2188.     
  2189.     if( stackPtr->mark <= 0 )
  2190.         DebugStr( "\pstackPtr->mark<=0" );
  2191.         
  2192.     #endif
  2193.     
  2194.     stackPtr->mark -= 1;        // stack[ mark ] is now the last ink
  2195.     
  2196.     blockPtr = & (* stackPtr->stack)[ stackPtr->mark ];        // make room for the new ink
  2197.  
  2198.     GXDisposeInk( blockPtr->tm );
  2199.     GXDisposeShape( blockPtr->sh );
  2200.     
  2201.     // check to see if we need to shrink the stack
  2202.     
  2203.     if( ( 2 * kStackListIncrement ) < ( stackPtr->count - stackPtr->mark ) )
  2204.         {
  2205.             SetHandleSize((Handle) stackPtr->stack, sizeof( TTModeBlock ) *
  2206.                                                                                             ( stackPtr->count - kStackListIncrement ) );
  2207.             ncheck( MemError() );
  2208.  
  2209.             stackPtr->count -= kStackListIncrement;
  2210.         }
  2211.         
  2212.     // now remove the clip from the transform stack
  2213.     
  2214.     TMRemoveTMClip( &( shstackPtr->tr ) );
  2215. }
  2216. /*----------------------------------------------------------------------------------
  2217.  
  2218.     TMPeekTMBlock
  2219.     
  2220.         this routine pops the topmost block from the transfer mode list.
  2221.                                                 
  2222. ----------------------------------------------------------------------------------*/
  2223. void TMPeekTMBlock( long *indxptr, long *countptr, gxRectangle *shbboxptr, TTModeStack *stackPtr )
  2224. {
  2225.     TTModeBlock     *blockPtr;
  2226.     
  2227.     check( 0 < stackPtr->mark );
  2228.     
  2229.     blockPtr = & (* stackPtr->stack)[ stackPtr->mark - 1 ];
  2230.     
  2231.     if( indxptr != nil )
  2232.         *indxptr = blockPtr->mark;
  2233.         
  2234.     if( countptr != nil )
  2235.         *countptr = blockPtr->count;
  2236.         
  2237.     if( shbboxptr != nil )
  2238.         *shbboxptr = blockPtr->shbbox;
  2239.     
  2240. }
  2241. /*----------------------------------------------------------------------------------
  2242.  
  2243.     TMBumpTMBlock
  2244.     
  2245.         this routine increments the mark for a block.  should maybe make it a macro.
  2246.                                                 
  2247. ----------------------------------------------------------------------------------*/
  2248. void TMBumpTMBlock( TTModeStack *stackPtr, TShapeStack *shstackPtr )
  2249. {
  2250.     TTModeBlock     *blockPtr;
  2251.     
  2252.     blockPtr = & (* stackPtr->stack)[ stackPtr->mark - 1 ];
  2253.     
  2254.     blockPtr->mark = shstackPtr->index + 1;
  2255. }
  2256. /*----------------------------------------------------------------------------------
  2257.  
  2258.     TMCombineColors
  2259.     
  2260.         this routine calculates what the color should be by combining the inks in the
  2261.         ink blocks.
  2262.                                                 
  2263. ----------------------------------------------------------------------------------*/
  2264. void TMCombineColors( gxColor *shcolorptr, gxInk shink, TTModeStack *stackPtr )
  2265. {
  2266.     TTModeBlock    *blockPtr;
  2267.     short                 indx;
  2268.         
  2269.     GXCombineColor( TMMakeWhite( shcolorptr ), shink );            // we start with white
  2270.  
  2271.     if( stackPtr != nil )
  2272.         {
  2273.             check( 0 < stackPtr->mark );
  2274.         
  2275.             indx = stackPtr->mark - 1;        // these are the number of inks in the stack
  2276.             
  2277.             check( 0 <= indx );
  2278.             
  2279.             HLock((Handle) stackPtr->stack );
  2280.             
  2281.             blockPtr = & (* stackPtr->stack)[ indx ];
  2282.             
  2283.             for( ; indx >= 0; --indx )
  2284.                 {
  2285.                     GXCombineColor( shcolorptr, blockPtr->tm );
  2286.                     
  2287.                     blockPtr -= 1;
  2288.                 }
  2289.             
  2290.             HUnlock((Handle) stackPtr->stack );
  2291.         }
  2292.     
  2293. }
  2294. /*----------------------------------------------------------------------------------
  2295.  
  2296.     TMTestIdentityMapping
  2297.     
  2298.         this routine returns true if the mapping passed to it is the identity mapping.
  2299.                                                 
  2300. ----------------------------------------------------------------------------------*/
  2301. Boolean TMTestIdentityMapping( gxMapping * themap )
  2302. {
  2303.      Fixed        *fixptr;
  2304.  
  2305.         fixptr = & ( themap->map[ 0 ][ 0 ] );
  2306.                     
  2307.         return( ( *fixptr++ == ff( 1 ) ) &&
  2308.                         ( *fixptr++ == ff( 0 ) ) &&
  2309.                         ( *fixptr++ == ff( 0 ) ) &&
  2310.                         
  2311.                         ( *fixptr++ == ff( 0 ) ) &&
  2312.                         ( *fixptr++ == ff( 1 ) ) &&
  2313.                         ( *fixptr++ == ff( 0 ) ) &&
  2314.                         
  2315.                         ( *fixptr++ == ff( 0 ) ) &&
  2316.                         ( *fixptr++ == ff( 0 ) ) &&
  2317.                         ( *fixptr   == fract1 )
  2318.                     );    
  2319. }
  2320. /*----------------------------------------------------------------------------------
  2321.  
  2322.     TMTestPerspectiveShape
  2323.     
  2324.         this routine returns true if the mapping for a shape has perspective.
  2325.                                                 
  2326. ----------------------------------------------------------------------------------*/
  2327. Boolean TMTestPerspectiveShape( gxShape sh )
  2328. {
  2329.     Fixed        *fixptr;
  2330.     gxMapping  themap;
  2331.     
  2332.     fixptr = (Fixed *) GXGetShapeMapping( sh, &themap );
  2333.                     
  2334.     return( ( fixptr[ 2 ] != 0 )    ||
  2335.                     ( fixptr[ 5 ] != 0 ) );
  2336. }
  2337.  
  2338. /*-------------------------------------------------------------------------------
  2339.     
  2340.     TMBoundsToPoints
  2341.     
  2342.         this routine takes a rectangle and makes four points out of them.
  2343.  
  2344. -------------------------------------------------------------------------------*/
  2345. void TMBoundsToPoints( gxPoint boxp[], const gxRectangle *box )
  2346. {
  2347.     boxp[ 0 ].x = boxp[ 1 ].x = box->left;
  2348.     boxp[ 0 ].y = boxp[ 2 ].y = box->top;
  2349.     boxp[ 2 ].x = boxp[ 3 ].x = box->right;
  2350.     boxp[ 1 ].y = boxp[ 3 ].y = box->bottom;
  2351. }
  2352. /*-------------------------------------------------------------------------------
  2353.     
  2354.     TMPointsToBounds
  2355.     
  2356.         this routine takes four points and makes a rectangle.
  2357.  
  2358. -------------------------------------------------------------------------------*/
  2359. void TMPointsToBounds( gxRectangle *box, const gxPoint *boxp )
  2360. {
  2361.     Fixed    scratch;
  2362.     
  2363.     scratch = boxp[ 0 ].x;            // left
  2364.     if( boxp[ 1 ].x < scratch )    scratch = boxp[ 1 ].x;
  2365.     if( boxp[ 2 ].x < scratch )    scratch = boxp[ 2 ].x;
  2366.     if( boxp[ 3 ].x < scratch ) scratch = boxp[ 3 ].x;
  2367.     box->left = scratch;
  2368.     
  2369.     scratch = boxp[ 0 ].y;            // top
  2370.     if( boxp[ 1 ].y < scratch ) scratch = boxp[ 1 ].y;
  2371.     if( boxp[ 2 ].y < scratch ) scratch = boxp[ 2 ].y;
  2372.     if( boxp[ 3 ].y < scratch ) scratch = boxp[ 3 ].y;
  2373.     box->top = scratch;
  2374.     
  2375.     scratch = boxp[ 0 ].x;            // right
  2376.     if( scratch < boxp[ 1 ].x )    scratch = boxp[ 1 ].x;
  2377.     if( scratch < boxp[ 2 ].x )    scratch = boxp[ 2 ].x;
  2378.     if( scratch < boxp[ 3 ].x )    scratch = boxp[ 3 ].x;
  2379.     box->right = scratch;
  2380.     
  2381.     scratch = boxp[ 0 ].y;            // bottom
  2382.     if( scratch < boxp[ 1 ].y ) scratch = boxp[ 1 ].y;
  2383.     if( scratch < boxp[ 2 ].y ) scratch = boxp[ 2 ].y;
  2384.     if( scratch < boxp[ 3 ].y ) scratch = boxp[ 3 ].y;
  2385.     box->bottom = scratch;    
  2386. }
  2387.  
  2388.  
  2389. /*-------------------------------------------------------------------------------
  2390.  
  2391.     TMCombineBitmapColors
  2392.         
  2393.         this routine applies the effect of a transfer mode to a bitmap.  NOTE it
  2394.         leaves the ink on the shape the same as the original shape.
  2395.         
  2396.             sh                ->        the shape which is the bitmap that we need to apply the
  2397.                                             colors to.
  2398.             shink            ->        the ink for the shape which it had originally.
  2399.             stackPtr    ->        a list of transfer modes which are to be applied to the
  2400.                                             shape in addition to the one in shink.
  2401.             boxptr        ->        if not nil then only make a bitmap which occupies this
  2402.                                             bounds.  the box is in device space.
  2403.             listPtr        ->        use this stack of transforms to interpret the space 
  2404.                                             of the boxptr in shape space.
  2405. -------------------------------------------------------------------------------*/
  2406.  
  2407. gxShape TMCombineBitmapColors( gxShape sh, gxInk shink, TTModeStack *stackPtr, 
  2408.                                                          gxRectangle *boxptr, TTransformList *listPtr )
  2409. {
  2410.     OSErr         status;
  2411.         
  2412.     gxBitmap        thebits;
  2413.     gxPoint            where;
  2414.     
  2415.     check( GXGetShapeType( sh ) == gxBitmapType );
  2416.     
  2417.     (void) GXGetBitmap( sh, &thebits, &where );
  2418.     
  2419.     // firgure out if this shape has a color set or direct data
  2420.     
  2421.     if( ( thebits.space == gxIndexedSpace ) && ( thebits.set != nil ) )
  2422.         {
  2423.             Handle                tempHdl;
  2424.             gxSetColor         *setptr;
  2425.             long                    setcount;
  2426.             long                    setindx;
  2427.             
  2428.             gxColor                    tempcolor;
  2429.             gxColorSpace        tempspace;
  2430.             
  2431.             tempcolor.profile = nil;
  2432.  
  2433.             // make a new shape and a new color set which has the transfer mode applied to it
  2434.             
  2435.             setindx = setcount = GXGetColorSet( thebits.set, &tempcolor.space, nil );
  2436.  
  2437.             if( 0 < setindx )
  2438.                 {
  2439.                     gxInk        tempink = GXCopyToInk( nil, shink );
  2440.                     
  2441.                     tempHdl = NewHandle( setcount * sizeof( gxSetColor ) ); 
  2442.                     nrequire_action( status = MemError(), TempColorSetFailed, sh = GXCloneShape( sh ); );
  2443.                     
  2444.                     HLock( tempHdl );
  2445.  
  2446.                     setptr = * (gxSetColor **) tempHdl;
  2447.                     
  2448.                     (void) GXGetColorSet( thebits.set, &tempspace, setptr );
  2449.                     
  2450.                     do
  2451.                         {
  2452.                             tempcolor.space = tempspace;
  2453.                             
  2454.                             * ((TTMColorValues *) &tempcolor.element ) = * ((TTMColorValues *)setptr);
  2455.                             
  2456.                             GXSetInkColor( tempink, &tempcolor );
  2457.                             
  2458.                             TMCombineColors( &tempcolor, tempink, stackPtr );
  2459.  
  2460.                             GXConvertColor( &tempcolor, gxRGBSpace, nil, nil );
  2461.                             
  2462.                             * ((TTMColorValues *) setptr) = * ((TTMColorValues *) &tempcolor.element );
  2463.                             
  2464.                             setptr += 1;
  2465.                     
  2466.                         } while( 0 < --setindx );
  2467.                                         
  2468.                     // fix the pointer to the color set
  2469.                     
  2470.                     setptr = * (gxSetColor **) tempHdl;
  2471.                     
  2472.                     thebits.set = GXNewColorSet( gxRGBSpace, setcount, setptr );
  2473.  
  2474.                     HUnlock( tempHdl );
  2475.                     DisposeHandle( tempHdl );
  2476.                     
  2477.                     GXDisposeInk( tempink );
  2478.                     
  2479.                     GXSetBitmap( sh = GXCopyToShape( nil, sh ), &thebits, &where );    
  2480.                     GXSetShapeInk( sh, shink = GXNewInk() );
  2481.  
  2482.                     GXDisposeInk( shink );
  2483.                     GXDisposeColorSet( thebits.set );
  2484.                 }
  2485.         }
  2486.     else if( thebits.space != gxIndexedSpace )
  2487.         {
  2488.             gxShape                sh2;
  2489.             gxShape                full;
  2490.             
  2491.             offscreen            os;
  2492.             
  2493.             gxInk                        saveink;
  2494.             gxTransform            savetransform;
  2495.             gxMapping                tempmap;
  2496.             gxColor                    tempcolor;
  2497.             
  2498.             // we need to create an offscreen bitmap and re-render the bitmap into it
  2499.             // also, for every ink in the resolver stack we need to apply the bitmap to
  2500.             
  2501.             // make a new bitmap but don't copy the bits 
  2502.             
  2503.             sh2 = TMGetBitmapPart( sh, boxptr, listPtr, &where );
  2504.             
  2505.             CreateOffscreen( &os, sh2 );
  2506.             TMAdjustOffscreenDevice( &os, &where );
  2507.                         
  2508.             // we first need to make a white shape and draw it to the offscreen.  then 
  2509.             // we draw the bitmap into the offscreen using the ink that is passed in
  2510.  
  2511.             full = GXNewShape( gxFullType );
  2512.             GXSetShapeTransform( full, os.xform );                            // make sure that this draws offscreen
  2513.             GXSetShapeColor( full, TMMakeWhite( &tempcolor ) );
  2514.  
  2515.             // ## for every DrawShape below we need to make sure that gx graphics gives up time
  2516.             // ## if not we'll get everyone and their brother screaming at us
  2517.  
  2518.             GXDrawShape( full );                                            // this clears the offscreen
  2519.             
  2520.             // now draw our bitmap into the offscreen with the transfer mode that we were given
  2521.             
  2522.             saveink = GXCloneInk( GXGetShapeInk( sh ) );
  2523.             GXSetShapeInk( sh, shink );
  2524.             savetransform = GXCloneTransform( GXGetShapeTransform( sh ) );
  2525.             GXSetShapeTransform( sh, os.xform );
  2526.             
  2527.             GXDrawShape( sh );            // blits the given bitmap into the offscreen with the tm
  2528.             
  2529.             GXSetShapeInk( sh, saveink ); GXDisposeInk( saveink );
  2530.             GXSetShapeTransform( sh, savetransform ); GXDisposeTransform( savetransform );
  2531.             
  2532.             // now we need to apply all of the transfer modes which are on the stack already
  2533.             
  2534.             if( stackPtr != nil )
  2535.                 {
  2536.                     short                    indx;
  2537.                     TTModeBlock     *blockPtr;
  2538.                     
  2539.                     check( 0 < stackPtr->mark );
  2540.                     
  2541.                     indx = stackPtr->mark - 1;                        // these are the number of inks on the stack
  2542.                     
  2543.                     HLock((Handle) stackPtr->stack );
  2544.                     
  2545.                     blockPtr = & (* stackPtr->stack)[ indx ];
  2546.                     
  2547.                     for( ; indx >= 0; --indx )
  2548.                         {
  2549.                             GXSetShapeInk( full, blockPtr->tm );
  2550.                             GXDrawShape( full );
  2551.                             
  2552.                             blockPtr -= 1;
  2553.                         }
  2554.                     
  2555.                     HUnlock((Handle) stackPtr->stack );
  2556.                 }
  2557.             
  2558.             GXDisposeShape( full );
  2559.             DisposeOffscreen( &os );
  2560.                         
  2561.             GXSetShapeMapping( sh2, GXGetShapeMapping( sh, &tempmap ) );
  2562.             
  2563.             sh = sh2;            // this is the shape that we return
  2564.         }
  2565.  
  2566. TempColorSetFailed:        
  2567.     return( sh );
  2568. }
  2569.  
  2570. /*-------------------------------------------------------------------------------
  2571.  
  2572.     TMGetBitmapPart
  2573.         
  2574.         this routine sets up a bitmap record in preparation for redering a part of
  2575.         if offscreen.
  2576.         
  2577. -------------------------------------------------------------------------------*/
  2578. gxShape TMGetBitmapPart( gxShape sh, gxRectangle *bbox, TTransformList *listPtr, gxPoint *where )
  2579. {
  2580.     gxRectangle    localbbox;
  2581.     
  2582.     gxBitmap        thebits;
  2583.     gxPoint            where2;
  2584.     gxShape            sh2;
  2585.  
  2586.     gxMapping        newmap;
  2587.     
  2588.     GXGetBitmap( sh, &thebits, &where2 );
  2589.  
  2590.     if( bbox != nil )
  2591.         {
  2592.             if( listPtr != nil && TMGetDeviceMapping( &newmap, sh, listPtr ) )
  2593.                 {
  2594.                     gxPoint            corners[ 4 ];
  2595.                     gxMapping        invmap;
  2596.  
  2597.                     InvertMapping( &invmap, &newmap );
  2598.                     TMBoundsToPoints( corners, bbox );
  2599.                     MapPoints( &invmap, 4, corners );
  2600.                     TMPointsToBounds( &localbbox, corners );
  2601.                 }
  2602.             else
  2603.                 {
  2604.                     localbbox = *bbox;
  2605.                 }
  2606.         
  2607.             #define FixedFloor( x )        ((long) (x) & 0xFFFF0000)
  2608.             #define FixedCeiling( x )    ((long) ((x) + 0xFFFF) & 0xFFFF0000)
  2609.  
  2610.             where2.x = localbbox.left;
  2611.             where2.y = localbbox.top;
  2612.             
  2613.             // the reson for rounding here is to >> by 16 -- the floor and ceiling deal with the frac part
  2614.             
  2615.             thebits.width = FixedRound( FixedCeiling( localbbox.right ) - FixedFloor( localbbox.left ) );
  2616.             thebits.height = FixedRound( FixedCeiling( localbbox.bottom ) - FixedFloor( localbbox.top ) );
  2617.             
  2618.             check( thebits.width > 0 );
  2619.             check( thebits.height > 0 );
  2620.             
  2621.             #undef FixedFloor
  2622.             #undef FixedCeiling
  2623.         }
  2624.         
  2625.     thebits.image = nil;
  2626.     thebits.pixelSize = 32;
  2627.     thebits.space = gxRGB32Space;
  2628.     thebits.set = nil;
  2629.     thebits.profile = nil;
  2630.     thebits.rowBytes = 0;
  2631.     
  2632.     // ## at some point when we need to take the resolution of the device
  2633.     // ## into account so that we can set up the mapping in the shape well
  2634.     
  2635.     sh2 = GXNewBitmap( &thebits, &where2 );
  2636.     
  2637.     *where = where2;
  2638.     
  2639.     return( sh2 );
  2640.     
  2641. }
  2642.  
  2643. /*-------------------------------------------------------------------------------
  2644.  
  2645.     TMGetDeviceMapping
  2646.         
  2647.         this routine concatenates all of the mapping on the stack and returns 
  2648.         a mapping which when applied to a set of points will map them from shape
  2649.         space into device space.  the mapping can be inverted to obtain a maping
  2650.         which goes from device space to shape space.
  2651.         
  2652. -------------------------------------------------------------------------------*/
  2653.  
  2654. Boolean TMGetDeviceMapping( gxMapping *newmap, gxShape sh, TTransformList *listptr )
  2655. {
  2656.     gxMapping            themap;
  2657.     gxTransform     *trptr;
  2658.  
  2659.     short                indx;
  2660.     Boolean            usemapping;
  2661.     
  2662.     (void) GXGetShapeMapping( sh, newmap );
  2663.         
  2664.     if( 0 <= ( indx = listptr->mark - listptr->top - 1 ) )    // a zero based count of the transforms
  2665.         {
  2666.             check( 0 <= indx );
  2667.             
  2668.             trptr = & (* listptr->list)[ listptr->mark - 1 ];
  2669.             
  2670.             // the next step is to the the clip's mapping into device space
  2671.             
  2672.             for( ; indx >= 0; --indx )
  2673.                 {
  2674.                     GXGetTransformMapping( *trptr, &themap );
  2675.                     MapMapping( newmap, &themap );
  2676.                                 
  2677.                     trptr -= 1;
  2678.                 }
  2679.             
  2680.             usemapping = true;
  2681.         }
  2682.     else
  2683.         {
  2684.             usemapping = ( TMTestIdentityMapping( newmap ) ) ? false : true;
  2685.         }
  2686.  
  2687.     return( usemapping );
  2688. }
  2689.  
  2690. /*-------------------------------------------------------------------------------
  2691.  
  2692.     TMResolveBitmap
  2693.         
  2694.         this routine takes a shape stack which is currently pointed to a bitmap and
  2695.         produces a bitmap that has the transfer modes resolved on it.  this routine
  2696.         also can take a stack of transfer modes which it will apply to the shape
  2697.         after it is done rendering all of the other shapes into it.
  2698.         
  2699.             stackPtr                ->            the stack pointer which contains all of the shapes.
  2700.             tmPtr                        ->            a list of transfer modes which need to be applied
  2701.                                                             to the bitmap after we are all done rendering offscreen.
  2702.             boxptr                    ->            only render this part of the shape (in device space).
  2703.         
  2704. -------------------------------------------------------------------------------*/
  2705. gxShape TMResolveBitmap( TShapeStack    *stackPtr, TTModeStack *tmPtr, gxRectangle *boxptr )
  2706. {
  2707.     gxPoint        where;
  2708.     
  2709.     gxShape        sh;
  2710.     gxShape        full;
  2711.     gxColor        tempcolor;
  2712.     
  2713.     offscreen        os;
  2714.     
  2715.     long        count;
  2716.  
  2717.     TRNABlock        rna;
  2718.     
  2719.     check( 0 < stackPtr->index );
  2720.     
  2721.     sh = TMGetBitmapPart( stackPtr->sh, boxptr, nil, &where );
  2722.     
  2723.     CreateOffscreen( &os, sh );
  2724.     TMAdjustOffscreenDevice( &os, &where );
  2725.  
  2726.     full = GXNewShape( gxFullType );
  2727.     GXSetShapeTransform( full, os.xform );
  2728.     GXSetShapeColor( full, TMMakeWhite( &tempcolor ) );
  2729.     
  2730.     GXDrawShape( full );
  2731.     
  2732.     count = stackPtr->index;
  2733.     
  2734.     TMFreeShape( stackPtr );
  2735.     TMRewindStack( stackPtr );
  2736.  
  2737.     do
  2738.         {
  2739.             gxShape             sh2;
  2740.  
  2741.             rna.root = nil;
  2742.             rna.branch = nil;
  2743.             rna.node = nil;
  2744.             rna.seed = 0;
  2745.             
  2746.             TMAttachShape( &rna, TMNextShape( stackPtr ), nil, stackPtr );
  2747.             
  2748.             if( rna.root != nil )
  2749.                 sh2 = GXCloneShape( rna.root );
  2750.             else
  2751.                 sh2 = GXNewPicture( 1, &rna.node, &rna.rootst, &rna.roottm, &rna.roottr );
  2752.             
  2753.             GXSetShapeTransform( sh2, os.xform );
  2754.             
  2755.             GXDrawShape( sh2 );            // this draws it offscreen
  2756.             
  2757.             GXDisposeShape( sh2 );
  2758.             
  2759.             if( rna.root != nil )
  2760.                 {
  2761.                     GXDisposeShape( rna.root );
  2762.                 }
  2763.             else
  2764.                 {
  2765.                     GXDisposeShape( rna.node );
  2766.                     
  2767.                     if( rna.rootst != nil )        GXDisposeStyle( rna.rootst );
  2768.                     if( rna.roottm != nil )        GXDisposeInk( rna.roottm );
  2769.                     if( rna.roottr != nil )        GXDisposeTransform( rna.roottr );
  2770.                 }
  2771.                         
  2772.         } while( stackPtr->index < count );
  2773.         
  2774.     // when we get here the stack is pointing to the bitmap shape again
  2775.     
  2776.     if( tmPtr != nil )
  2777.         {
  2778.             short                    indx;
  2779.             TTModeBlock     *blockPtr;
  2780.  
  2781.             // we now have to apply all of the transfer modes which are on the stack
  2782.             
  2783.             check( 0 < tmPtr->mark );
  2784.             
  2785.             indx = tmPtr->mark - 1;                        // these are the number of inks on the stack
  2786.                         
  2787.             HLock((Handle) tmPtr->stack );
  2788.             
  2789.             blockPtr = & (* tmPtr->stack)[ 0 ];
  2790.             
  2791.             for( ; indx >= 0; --indx )
  2792.                 {
  2793.                     GXSetShapeInk( full, blockPtr->tm );
  2794.                     GXDrawShape( full );
  2795.                     
  2796.                     blockPtr += 1;
  2797.                 }
  2798.             
  2799.             HUnlock((Handle) tmPtr->stack );
  2800.         }
  2801.         
  2802.     // finally compute the clip for this shape
  2803.     
  2804.     {
  2805.         TTransformList    *listptr = &stackPtr->tr;
  2806.         
  2807.         gxRectangle    bounds;
  2808.         gxShape clip;
  2809.         gxShape    other;
  2810.  
  2811.         gxTransform    *trptr;
  2812.  
  2813.         gxMapping    map;
  2814.         
  2815.         short        indx;
  2816.         
  2817.         GXGetShapeBounds( stackPtr->sh, 0, &bounds );    // the original bitmap on the stack
  2818.         clip = GXNewRectangle( &bounds );
  2819.  
  2820.         other = GXGetShapeClip( stackPtr->sh );
  2821.         GXIntersectShape( clip, other );
  2822.         GXDisposeShape( other );
  2823.  
  2824.         GXGetShapeMapping( stackPtr->sh, &map );
  2825.         GXMapShape( clip, &map );
  2826.  
  2827.         // walk the transform list and come up with a clip for this shape
  2828.  
  2829.         if( 0 <= ( indx = listptr->mark - listptr->top - 1 ) )    // a zero based count of the transforms
  2830.             {
  2831.                 check( 0 <= indx );
  2832.                 
  2833.                 trptr = & (* listptr->list)[ listptr->mark - 1 ];
  2834.                 
  2835.                 // the next step is to the the clip's mapping into device space
  2836.                 
  2837.                 for( ; indx >= 0; --indx )
  2838.                     {
  2839.                         other = GXGetTransformClip( *trptr );
  2840.                         GXIntersectShape( clip, other );
  2841.                         GXDisposeShape( other );
  2842.                         
  2843.                         GXGetTransformMapping( *trptr, &map );
  2844.                         GXMapShape( clip, &map );
  2845.                                     
  2846.                         trptr -= 1;
  2847.                     }
  2848.             }
  2849.  
  2850.         GXSetShapeClip( sh, clip );
  2851.         GXDisposeShape( clip );
  2852.     }
  2853.     
  2854.     GXDisposeShape( full );
  2855.     DisposeOffscreen( &os );
  2856.     
  2857.     return( sh );
  2858.     
  2859. }
  2860. /*-------------------------------------------------------------------------------
  2861.  
  2862.     TMMakeWhite
  2863.         
  2864.         this routine takes a color data structure and fills it in with white.
  2865.         
  2866. -------------------------------------------------------------------------------*/
  2867. gxColor *TMMakeWhite( gxColor *colorptr )
  2868. {
  2869.     colorptr->space = gxRGBSpace;
  2870.     colorptr->profile = nil;
  2871.     colorptr->element.rgb.red = 0xFFFF;
  2872.     colorptr->element.rgb.green = 0xFFFF;
  2873.     colorptr->element.rgb.blue  = 0xFFFF;
  2874.     
  2875.     return( colorptr );
  2876. }
  2877.